You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Socket.io仅在两端重启后发消息,切换聊天室无实时消息求助

解决Socket.io实时消息异常问题

问题现象

  • 仅服务端和客户端都重启后,Socket.io才能正常即时发送消息
  • 用户切换聊天室后无法接收实时消息,需重启两端恢复
  • 能通过console.log看到Socket.io传来的数据,但消息无法更新到界面

服务端代码修正

1. 修复用户SocketID更新逻辑

当前addUser未处理同一用户重复添加的情况,导致切换聊天室后用户的SocketID未更新,消息仍发往旧连接。修改addUser函数:

function addUser(user: userSocketAttributes) {
  // 先移除该用户的旧记录,再添加新的SocketID
  users = users.filter(u => u.userId !== user.userId);
  users.push(user);
}

2. 增加用户在线状态判断

发送消息前需确认接收用户是否在线,避免向无效SocketID发送消息:

socket.on("sendMessage", async (messageAttributes: socketMessageAttributes)=>{
  const user = findUser(messageAttributes.recieverId);
  if (!user) {
    console.log(`用户${messageAttributes.recieverId}未在线,消息无法实时推送`);
    return;
  }

  const authToken = JWT_Helper_verify(messageAttributes.auth) as JwtPayload;
  try {
    const userid = await CreateCustomer.findOne({where:{id: authToken?.id}});
    const support = await CreateCustomer.findOne({where: {user_username: 'support'}});

    io.to(user.socketId).emit("getMessage", messageAttributes);
  } catch (error) {
    console.log(error);
  }
})

客户端代码修正

1. 清理旧Socket连接

切换聊天室时未断开旧连接,导致多连接冲突,需在组件卸载或聊天室切换时断开旧连接:

useEffect(()=>{
  // 断开之前的Socket连接
  if (socket.current) {
    socket.current.disconnect();
  }
  socket.current = io(socket_URL);
  socket.current.emit('addUser', userDetails?.role === 'support' ? data?.conversation?.recieverId : userDetails?.id);

  // 组件卸载时清理连接
  return () => {
    if (socket.current) {
      socket.current.disconnect();
    }
  };
}, [data?.conversation?.id])

2. 修复消息监听的闭包问题

原监听逻辑未使用函数式更新,导致无法获取最新的chatMessages状态,且未清理旧监听导致重复绑定:

useEffect(()=>{
  if (!socket.current) return;

  const handleNewMessage = (item: any) => {
    if(data?.conversation?.id === item?.conversationId){
      // 使用函数式更新获取最新的消息数组
      setChatMessages(prevMessages => [...prevMessages, item]);
    }    
  };

  socket.current.on("getMessage", handleNewMessage);

  // 清理函数移除监听,避免内存泄漏
  return () => {
    socket.current?.off("getMessage", handleNewMessage);
  };
}, [data?.conversation?.id, socket.current])

3. 切换聊天室时重新拉取消息

确保切换聊天室后能获取最新的历史消息:

useEffect(()=>{
  fetchMessages();
}, [data?.conversation?.id]) // 添加聊天室ID作为依赖,切换时触发

内容的提问来源于stack exchange,提问作者kingsJayson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 16:37:40