Node.js中setInterval引发全局重连问题的修复需求
问题:修复客户端自动重连时触发所有客户端的问题
我正在实现网站内客户端自动重连功能,原本运行正常,但添加setInterval定时器后,连接恢复时会触发所有客户端重连,而非目标客户端。需要修复Node.js中的setInterval逻辑,避免重连时影响所有客户端。
相关代码
io.on("connection", function (socket) { if (socket.recovered) { if(UserInfo[socket.id]){ clearInterval(reconnct); } const isoffonline = OnlineUser.findIndex((v) => v.id == socket.id); if (isoffonline != -1) { OnlineUser[isoffonline].stat = 5; socket.join(UserInfo[socket.id]['idroom']); io.emit("SEND_EVENT_EMIT_SERVER", { cmd: "USERS_UR", data: [socket.id, UserInfo[socket.id]['idroom']] }); io.emit("SEND_EVENT_EMIT_SERVER", { cmd: "u^", data: OnlineUser[isoffonline] }); } } else { } socket.emit("SEND_EVENT_EMIT_SERVER", { cmd: "pw", data: ShowPowers }); socket.on("disconnect", function (v) { if (UserInfo[socket.id]) { if(SiteSetting.reconnect && UserInfo[socket.id]['islogin'] == "عضو"){ if(ListEnter.length > 0){ ListEnter.splice(ListEnter.findIndex((v) => v.id == socket.id),1); }; const isoffonline = OnlineUser.findIndex((v) => v.id == socket.id); if (isoffonline != -1) { OnlineUser[isoffonline]['stat'] = 5; OnlineUser[isoffonline]['idroom'] = null; socket.leave(UserInfo[socket.id]['idroom']); io.emit("SEND_EVENT_EMIT_SERVER", { cmd: "u^", data: OnlineUser[isoffonline] }); io.emit("SEND_EVENT_EMIT_SERVER", { cmd: "USERS_UR", data: [socket.id, null] }); } reconnct = setInterval(()=>{ socket.emit("SEND_EVENT_EMIT_SERVER", { cmd: "ev", data: "window.onbeforeunload = null; location.href=\"/\";" }); UserDisconnect({ id: socket.id, state: 1 }); },150000); }else{ if (UserInfo[socket.id]) { socket.emit("SEND_EVENT_EMIT_SERVER", { cmd: "ev", data: "window.onbeforeunload = null; location.href=\"/\";" }); UserDisconnect({ id: socket.id, state: 1 }); }; }; } });
问题根源
你使用了全局变量reconnct存储定时器ID,每个客户端断开连接时都会覆盖这个变量。当某个客户端连接恢复时,只能清除最后一个创建的定时器,之前的定时器仍在后台运行,导致所有对应的客户端都会被触发重连操作。
修复方案
核心思路是为每个socket单独绑定定时器ID,避免全局变量的冲突:
- 将定时器ID绑定到当前socket对象,使用
socket.reconnectTimer替代全局reconnct - 连接恢复时,清除当前socket对应的定时器,而非全局变量
- 确保定时器逻辑仅作用于当前socket,同时在必要时清理定时器防止内存泄漏
修改后的代码
io.on("connection", function (socket) { if (socket.recovered) { if(UserInfo[socket.id]){ // 清除当前socket对应的定时器 if (socket.reconnectTimer) { clearInterval(socket.reconnectTimer); socket.reconnectTimer = null; } } const isoffonline = OnlineUser.findIndex((v) => v.id == socket.id); if (isoffonline != -1) { OnlineUser[isoffonline].stat = 5; socket.join(UserInfo[socket.id]['idroom']); io.emit("SEND_EVENT_EMIT_SERVER", { cmd: "USERS_UR", data: [socket.id, UserInfo[socket.id]['idroom']] }); io.emit("SEND_EVENT_EMIT_SERVER", { cmd: "u^", data: OnlineUser[isoffonline] }); } } socket.emit("SEND_EVENT_EMIT_SERVER", { cmd: "pw", data: ShowPowers }); socket.on("disconnect", function (v) { if (UserInfo[socket.id]) { if(SiteSetting.reconnect && UserInfo[socket.id]['islogin'] == "عضو"){ if(ListEnter.length > 0){ ListEnter.splice(ListEnter.findIndex((v) => v.id == socket.id),1); }; const isoffonline = OnlineUser.findIndex((v) => v.id == socket.id); if (isoffonline != -1) { OnlineUser[isoffonline]['stat'] = 5; OnlineUser[isoffonline]['idroom'] = null; socket.leave(UserInfo[socket.id]['idroom']); io.emit("SEND_EVENT_EMIT_SERVER", { cmd: "u^", data: OnlineUser[isoffonline] }); io.emit("SEND_EVENT_EMIT_SERVER", { cmd: "USERS_UR", data: [socket.id, null] }); } // 将定时器绑定到当前socket对象 socket.reconnectTimer = setInterval(()=>{ socket.emit("SEND_EVENT_EMIT_SERVER", { cmd: "ev", data: "window.onbeforeunload = null; location.href=\"/\";" }); UserDisconnect({ id: socket.id, state: 1 }); },150000); }else{ if (UserInfo[socket.id]) { socket.emit("SEND_EVENT_EMIT_SERVER", { cmd: "ev", data: "window.onbeforeunload = null; location.href=\"/\";" }); UserDisconnect({ id: socket.id, state: 1 }); }; }; } });
额外建议:在客户端彻底断开(如disconnect事件触发且无需重连)时,也可以主动清除对应socket的定时器,进一步避免内存泄漏。
内容的提问来源于stack exchange,提问作者user19455465
相关产品推荐
相关产品推荐

