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

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,避免全局变量的冲突:

  1. 将定时器ID绑定到当前socket对象,使用socket.reconnectTimer替代全局reconnct
  2. 连接恢复时,清除当前socket对应的定时器,而非全局变量
  3. 确保定时器逻辑仅作用于当前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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 22:52:05