Socket.io实现注册用户一对一聊天离线场景最优解决方案咨询
Socket.io离线场景一对一聊天解决方案
你当前的实现已经完成了核心的消息持久化存储,仅需要补全两处逻辑即可解决接收方离线的问题:
1. 修复服务端离线场景报错
当前服务端代码在接收方离线时,getUser(receiverId)会返回空值,直接读取user.socketId会触发异常,修改sendMessage事件逻辑如下:
// 服务端socket.on("sendMessage") 部分修改 socket.on("sendMessage", ({ senderId, receiverId, text }) => { console.log("receiverid=====>>",receiverId) console.log("users ",users) const user = getUser(receiverId); console.log("userSocket Id",user) // 仅当接收方在线时实时推送消息 if (user) { io.to(user.socketId).emit("getMessage", { senderId, text, }); } // 离线场景无需额外操作,消息已经通过客户端的post接口存入数据库 });
2. 补充用户上线时的消息同步逻辑
你现有代码已经实现了进入单个会话时拉取历史消息的逻辑,可额外补充两个逻辑优化体验:
- 给消息表新增
isRead布尔字段,默认值为false,用于标记消息是否已读 - 用户建立Socket连接后,拉取所有属于自己的未读消息,更新会话列表的未读计数;用户打开对应会话时,标记该会话下的所有消息为已读
// 客户端Socket连接初始化部分补充逻辑 useEffect(() => { socket.current = io("ws://localhost:8900"); socket.current.on("getMessage", (data) => { setArrivalMessage({ sender: data.senderId, text: data.text, createdAt: Date.now(), }); // 收到的消息属于当前打开的会话时,标记为已读 if (currentChat?.members.includes(data.sender)) { axios.post("http://localhost:8080/api/messages/markRead", { conversationId: currentChat._id, senderId: data.sender }) } }); // 连接建立后拉取当前用户的未读消息总数,更新会话列表的未读提示 axios.get("http://localhost:8080/api/messages/unreadCount", { params: { userId: clientId } }).then(res => { // 自行处理返回结果,更新会话列表的未读标识 }) }, []);
可选扩展能力
如果需要支持多端登录同步,可修改服务端addUser逻辑,允许同一个userId绑定多个socketId,发消息时遍历所有绑定的socketId推送即可;如果需要离线通知能力,可对接浏览器Notification API或者移动端推送SDK,用户离线时触发推送。
内容的提问来源于stack exchange,提问作者Shehryar Tanoli
相关产品推荐
相关产品推荐

