Vue3实现即时通讯:如何处理WebSocket消息推送与会话管理?

新手上路,请多包涵

我打算用 Vue3 和 NestJS 写一个即时通讯的项目,现在关于消息和会话这一块有几个问题一直想不明白,所以想请教一下大家:
1.是只有当前会话的实时聊天用websocket推送,还是会话列表里所有的消息都用websocket推送呢?
2.vue中该怎么处理不同会话以及不同会话的聊天记录,Pinia中如何组织会话和聊天记录的数据结构?
3.websocket推送消息应该直接附带消息内容,还是只推送有新消息这个事件,然后让前端自己拉最新的信息呢?

实在是想不明白了,恳请各位大神不吝赐教!

下面是我自己的一些想法:

1.针对第一个问题,我的想法是,当前聊天的会话用websocket实时推送消息内容,会话列表其他的会话仅通过websocket推送未读数以及最后一条消息内容,这样可以吗?
2.针对第二个问题,我目前的想法是,pinia的会话仓库中存一下用户的会话列表,再存一下当前会话(就是和谁聊天)的聊天记录,切换会话的时候(换人聊天)更换仓库中当前会话的会话id,并重新拉取新会话的聊天记录。这个方案是否可行?

阅读 1.2k
avatarAI BotBETA

回答

1. 是只有当前会话的实时聊天用websocket推送,还是会话列表里所有的消息都用websocket推送呢?

回答:这主要取决于你的应用需求和性能考虑。通常,为了优化性能和减少服务器负载,只推送当前会话的实时聊天消息是比较合理的做法。对于会话列表中的其他会话,可以仅推送未读消息数量或最后一条消息的摘要,这样用户可以在不进入具体会话的情况下了解是否有新消息。你的方案(当前聊天的会话用websocket实时推送消息内容,会话列表其他会话仅推送未读数和最后一条消息)是可行的。

2. Vue中该怎么处理不同会话以及不同会话的聊天记录,Pinia中如何组织会话和聊天记录的数据结构?

回答

在Vue中使用Pinia管理状态是一个很好的选择。你可以按照以下方式组织数据结构:

  • 会话列表(Sessions Store):存储用户的所有会话,每个会话可以是一个对象,包含会话ID、对方用户信息、未读消息数、最后一条消息等。
  • 当前会话(Current Session Store):存储当前激活的会话的详细信息,包括聊天记录。聊天记录可以是一个数组,每个元素代表一条消息,包含发送者、接收者、时间戳、内容等。

Pinia Store 示例

// sessions.js (Pinia Store for Sessions)
export const useSessionsStore = defineStore('sessions', {
  state: () => ({
    sessions: [] // 存储会话列表
  }),
  actions: {
    updateSessions(newSessions) {
      this.sessions = newSessions;
    }
  }
});

// currentSession.js (Pinia Store for Current Session)
export const useCurrentSessionStore = defineStore('currentSession', {
  state: () => ({
    sessionId: null,
    messages: [] // 存储当前会话的聊天记录
  }),
  actions: {
    setCurrentSession(sessionId, messages) {
      this.sessionId = sessionId;
      this.messages = messages;
    },
    addMessage(message) {
      this.messages.push(message);
    }
  }
});

3. websocket推送消息应该直接附带消息内容,还是只推送有新消息这个事件,然后让前端自己拉最新的信息呢?

回答

这同样取决于你的具体需求和系统架构。如果消息量不大,且对实时性要求很高,直接通过WebSocket推送消息内容是更直接、高效的方式。这样前端可以立即显示新消息,无需额外请求。然而,如果消息量很大,或者出于安全、隐私考虑,你可能只想推送一个“有新消息”的通知,然后前端根据这个通知去拉取最新的消息。

总结:你的方案(当前会话实时推送消息内容,其他会话推送未读数和最后一条消息;使用Pinia管理会话和聊天记录)是合理的,但具体实现时还需考虑应用的具体需求和性能优化。

2 个回答
  1. 既然用了 WebSocket 那就都用 WebSocket,不然一个消息推送你要写两套(WebSocket 和 HTTP)
    实时推送和推送最后一条消息没有区别,因为新消息会变成新的最后一条消息被推送给客户端,就相当于实时推送了
  2. 聊天记录储存在数据库(IndexDB)中,进入会话或群聊就获取相应的聊天记录

WebSocket 部分仅与数据库通信,除了少数情况(如连接断开时提示用户)

进入会话时,获取数据库中的聊天记录,并且监听数据库变化,退出会话时移除监听

  1. 一个客户端通常只维护一个ws链接,然后通过自定义数据格式如{op:"xxx",msg:"xxx"}这种来处理不同的业务逻辑
  2. 一般来讲,注重隐私是在客户端存储消息,需要用到数据库,web的应用建议后端存,前端拉,只缓存最新的多少条
  3. 没必要单独拉,直接推整个消息,但是注意,媒体资源,一般是先上传后只推访问路径
推荐问题
宣传栏