Socket.io 多房间场景下用户离开原房间后仍接收该房间消息如何解决
Socket.io 房间切换异常:离开房间后仍可接收该房间推送消息
问题描述
基于Socket.io实现支持用户自由选择加入指定房间的功能,运行时出现异常:用户切换离开某房间后,自身发送的消息不会投递到该已离开的房间,但仍然能接收到该房间推送的消息。
相关实现代码
服务端代码
socket.on('create', function (msg) { socket.leave(msg.currentRoom); socket.join(msg.room); });
客户端代码
var socket = io.connect('https://nova.broyster.repl.co'); var message = document.getElementById("message"), username = document.getElementById("username"), room = document.getElementById("roomm"), feedback = document.getElementById("feedback"); pastRoom = room.value; document.getElementById("roomSubmit").addEventListener('click', function() { socket.emit('create', { room: room.value, currentRoom: pastRoom }); });
问题根因与修复方案
- 问题根源是客户端
pastRoom变量的更新逻辑存在缺陷:pastRoom仅在页面初始化时被赋值为输入框的初始值,后续每次用户提交切换房间后,都没有把刚加入的新房间值同步更新给pastRoom。
这会导致第二次及之后的房间切换请求中,currentRoom参数始终传的是页面最开始加载时的初始房间值,服务端执行leave操作时,只会去退出这个早就离开的初始房间,根本不会处理用户上一次加入的目标房间,最终socket仍然挂在第一次切换的房间频道里,自然能持续接收到该房间的推送消息。 - 优化思路:
- 服务端处理
leave、join这类异步操作时,等待操作真正完成后再给客户端返回切换成功的回执,避免异步时序错乱导致的状态不一致,优化后的服务端代码示例:
socket.on('create', async function (msg) { // 串行执行离开原房间、加入新房间的操作 await socket.leave(msg.currentRoom); await socket.join(msg.room); // 向客户端推送切换成功的通知 socket.emit('roomChangeSuccess', { newRoom: msg.room }); });- 客户端不要在发出切换请求后就默认房间已切换完成,要等收到服务端的成功回执后再更新本地的
pastRoom状态,示例代码:
// 监听服务端推送的房间切换成功事件 socket.on('roomChangeSuccess', function(res) { // 只有收到成功通知后,才更新本地记录的当前房间值 pastRoom = res.newRoom; }); - 服务端处理
内容的提问来源于stack exchange,提问作者Brody
相关产品推荐
相关产品推荐

