在线状态同步不及时,WebSocket 心跳怎么处理才靠谱?
我在做一个聊天应用,用 WebSocket 实现用户在线状态。目前的做法是用户连接时设为 online,断开就设 offline。但实际测试发现,如果用户直接关掉浏览器或者网络突然中断,服务端收不到 disconnect 事件,状态就一直卡在 online,其他用户看到的还是“在线”——这显然不对。
我尝试加了心跳机制,前端每隔 30 秒发个 ping,后端没收到就标记离线。但代码写得不太稳,有时候还是会漏判。下面是我 React 组件里的心跳逻辑,是不是哪里有问题?
useEffect(() => {
const ws = new WebSocket('wss://example.com/chat');
ws.onopen = () => {
const heartbeat = setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: 'ping' }));
}
}, 30000);
};
return () => {
clearInterval(heartbeat); // 这里其实会报错,heartbeat 作用域不对
ws.close();
};
}, []);
首先说说前端这块,heartbeat变量的作用域不对,应该在useEffect函数内定义。另外,建议用一个标志位来跟踪连接状态,避免重复设置定时器。这是修正后的代码:
后端这边也需要配合处理。光靠前端发心跳不够稳妥,服务端要主动监控连接状态。建议设置个超时时间,比如60秒收不到任何消息就断开连接。可以用Node.js的setTimeout来做:
记得把超时时间和心跳间隔错开一点,这样更稳当。折腾过几次才找到这个比较靠谱的方案,希望能帮到你。