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

Socket.io活跃用户列表旧标签页在用户断线重连后不更新的原因是什么?

在线用户列表状态不同步修复方案

核心问题根因

  • 服务端用户登录逻辑仅在socket连接初始化时广播一次在线用户,用户后续登录成功不会主动推送最新状态,导致旧标签页收不到重新上线的通知
  • 服务端存储用户socket连接时直接覆盖原有数组,会丢失同一个用户其他标签页的连接记录
  • 客户端通过record数组对上线用户做去重,同一个用户重新上线时因为用户ID已存在于数组中,不会触发重新渲染
  • 用户登出/断开连接时,服务端没有清理users对象中对应的失效连接记录

服务端代码修复

let users = {};
io.on("connection", async (socket) => {
    // 登录逻辑优化
    socket.on("login", async function(user_id) {
        socket.handshake.session.user_id = user_id;
        await socket.handshake.session.save();
        // 存储socket连接,不覆盖原有连接
        if (!users[user_id]) {
            users[user_id] = [];
        }
        if (!users[user_id].includes(socket.id)) {
            users[user_id].push(socket.id);
        }
        // 登录成功后广播最新在线用户列表
        await broadcastOnlineUsers();
    });
    // 登出逻辑优化
    socket.on("logout", async function(user_id) {
        if (socket.handshake.session.user_id) {
            delete socket.handshake.session.user_id;
            await socket.handshake.session.save();
            // 清理当前socket连接记录
            if (users[user_id]) {
                users[user_id] = users[user_id].filter(id => id !== socket.id);
                if (users[user_id].length === 0) {
                    delete users[user_id];
                }
            }
            await broadcastOnlineUsers();
        }
    });
    // 连接初始化逻辑优化
    const currentSession = socket.handshake.session.user_id;
    if (typeof currentSession !== "undefined" && typeof socket.id !== "undefined") {
        if (!users[currentSession]) {
            users[currentSession] = [];
        }
        if (!users[currentSession].includes(socket.id)) {
            users[currentSession].push(socket.id);
        }
        await broadcastOnlineUsers();
    }
    // 断开连接逻辑优化
    socket.on("disconnect", async () => {
        const userId = socket.handshake.session.user_id;
        if (userId && users[userId]) {
            // 清理失效连接
            users[userId] = users[userId].filter(id => id !== socket.id);
            if (users[userId].length === 0) {
                delete users[userId];
                const userLeft = await utils.getUserInfo(userId);
                io.emit("msg", utils.formatMessage("Bot", `${userLeft.name} has left the chat`));
            }
            await broadcastOnlineUsers();
        }
    });
    // 封装统一的在线用户广播方法
    async function broadcastOnlineUsers() {
        const onlineUserIds = Object.keys(users);
        const onlineUsers = [];
        for (const userId of onlineUserIds) {
            // 过滤掉所有连接都失效的用户
            const validSockets = users[userId].filter(id => io.sockets.sockets.has(id));
            if (validSockets.length > 0) {
                users[userId] = validSockets;
                onlineUsers.push(await utils.getUserInfo(userId));
            } else {
                delete users[userId];
            }
        }
        // 统一广播全量在线用户列表
        io.emit("onlineUsersUpdate", onlineUsers);
    }
})

客户端代码修复

// 统一监听全量在线用户更新事件,移除原有重复判断逻辑
socket.on("onlineUsersUpdate", onlineUsers => {
    const ul = document.querySelector(".the-ul");
    // 清空现有列表
    ul.innerHTML = "";
    // 重新渲染所有在线用户
    onlineUsers.forEach(user => {
        outputActiveUsers(user);
    });
})
// 保留原有业务逻辑不变
async function outputMessage(msg){
    let div=document.createElement("div");
    div.classList.add("msg-wrapper");
     div.innerHTML=`<div class="msg-wrapper">
                        <div class="msg">
                            <p>${msg.text}</p>
                        </div>
                        <span id="you-time" class="time">${msg.time}</span>
                    </div>`;
    document.querySelector(".msg-wrapper").appendChild(div);
}
function outputActiveUsers(msg){
    let li=document.createElement("li");
    li.classList.add("active-people-li");
    li.innerHTML= `<div class="active-sidebar">
                        <div class="div-of-img">
                            <img src="../files/profile.png" alt="" class="active-profile-img">
                        </div>
                        <div>
                            <a href=""><h4>${msg.name}</h4></a>
                            <h5>Hi. Is this you, bro?</h5>
                        </div>
                    </div>`;
    document.querySelector(".the-ul").appendChild(li);
}

HTML代码无需修改

<div class="active-people">
    <ul class="the-ul">
    </ul>
</div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 04:27:01