如何从客户端JS文件访问Server.js中的online_users全局变量
实现客户端获取并展示Socket.io在线用户列表
问题背景
我有一个Server.js文件,会将所有连接到服务器的客户端Socket ID添加到online_users列表中;另有一个客户端JavaScript文件,其中的showOnline方法会在点击“多人”按钮时触发模态框。我希望从该客户端JS文件中访问Server.js里的online_users列表,将在线用户列表展示在小型模态框内。
当前代码
Server.js
io.on('connection', (socket) => { console.log('user with ' + socket.id + ' connected'); // 将socket id添加到服务器的在线用户列表 online_users.push(socket.id); socket.on('joinRoom', (room) => { socket.join(room); console.log(`User joined room: ${room}`); }); socket.on('move', (data) => { const { room, message } = data; io.to(room).emit('move', message); }); socket.on('disconnect', () => { console.log('user disconnected'); // 从online_users列表中移除客户端(此处代码未完成) online_users.wh }); });
客户端JavaScript
// 展示在线用户的方法 // 应该每秒调用一次以获取实时更新 function showOnline() { // 从server.js暴露的全局变量中获取在线列表 // 程序化创建新表格,左侧显示头像,右侧显示用户的socket id $('#onlineModal').modal('show'); }
解决方案
1. 完善服务器端的用户移除逻辑
首先补全disconnect事件中的代码,确保用户断开连接时从列表中移除:
socket.on('disconnect', () => { console.log('user disconnected'); // 找到socket id在列表中的索引并移除 const index = online_users.indexOf(socket.id); if (index !== -1) { online_users.splice(index, 1); } });
2. 服务器端添加在线列表交互逻辑
有两种常见实现方式:
方式一:客户端主动请求在线列表
在Server.js中添加监听客户端请求的事件:
io.on('connection', (socket) => { // ... 原有代码 ... // 监听客户端获取在线列表的请求 socket.on('getOnlineUsers', () => { socket.emit('onlineUsers', online_users); }); });
方式二:服务器主动推送在线列表更新
当用户上线或下线时,主动把更新后的列表推送给所有客户端:
io.on('connection', (socket) => { console.log('user with ' + socket.id + ' connected'); online_users.push(socket.id); // 用户上线时推送更新后的列表 io.emit('onlineUsersUpdate', online_users); // ... 原有代码 ... socket.on('disconnect', () => { console.log('user disconnected'); const index = online_users.indexOf(socket.id); if (index !== -1) { online_users.splice(index, 1); } // 用户下线时推送更新后的列表 io.emit('onlineUsersUpdate', online_users); }); });
3. 客户端修改showOnline方法渲染列表
根据选择的方式修改客户端代码:
对应方式一(主动请求):
function showOnline() { // 向服务器请求在线用户列表 socket.emit('getOnlineUsers'); // 监听服务器返回的在线列表并渲染 socket.on('onlineUsers', (users) => { renderOnlineUsers(users); }); $('#onlineModal').modal('show'); } // 渲染在线用户表格的函数 function renderOnlineUsers(users) { const table = $('<table class="table table-sm"></table>'); // 添加表头 table.append('<thead><tr><th>头像</th><th>Socket ID</th></tr></thead>'); const tbody = $('<tbody></tbody>'); // 遍历用户列表生成行 users.forEach(userId => { const row = $('<tr></tr>'); // 用文字标签代替头像,可替换为图片 row.append('<td><span class="badge bg-primary">头像</span></td>'); row.append(`<td>${userId}</td>`); tbody.append(row); }); table.append(tbody); // 清空模态框内容并插入表格 $('#onlineModal .modal-body').empty().append(table); }
对应方式二(主动推送):
// 提前监听服务器推送的在线列表更新,缓存最新数据 let currentOnlineUsers = []; socket.on('onlineUsersUpdate', (users) => { currentOnlineUsers = users; }); function showOnline() { // 直接用缓存的在线列表渲染 renderOnlineUsers(currentOnlineUsers); $('#onlineModal').modal('show'); } // 渲染函数同上 function renderOnlineUsers(users) { const table = $('<table class="table table-sm"></table>'); table.append('<thead><tr><th>头像</th><th>Socket ID</th></tr></thead>'); const tbody = $('<tbody></tbody>'); users.forEach(userId => { const row = $('<tr></tr>'); row.append('<td><span class="badge bg-primary">头像</span></td>'); row.append(`<td>${userId}</td>`); tbody.append(row); }); table.append(tbody); $('#onlineModal .modal-body').empty().append(table); }
内容的提问来源于stack exchange,提问作者Anthony Kinyua
相关产品推荐
相关产品推荐

