Socket.io房间事件重复触发两次的问题解决求助
Socket.io房间事件触发两次的问题解决
问题原因
这不是Bug,是Socket.io的设计行为:
- 每个新连接的socket会自动加入以自身ID命名的房间,目的是方便单独向该socket推送消息,此时会触发一次
create-room事件(对应日志里的fa3x6j6Zq7HZiRgYAAAB这类随机字符串房间)。 - 当你调用
socket.join(channel_id)时,如果目标房间(比如demo)不存在,Socket.io会创建这个房间,再次触发create-room事件。
两次事件触发分别对应内部自动创建的socket ID房间,和你业务自定义的房间,属于正常逻辑。
解决方案
方案1:过滤非业务房间
在create-room事件监听中,过滤掉Socket.io自动创建的socket ID房间,只处理你的业务自定义房间:
io.of('/').adapter.on('create-room', (room) => { // 根据业务规则过滤,示例:排除16位随机字符串格式的socket ID房间 if (/^[A-Za-z0-9]{16}$/.test(room)) return; // 或根据业务房间的特定前缀过滤,比如业务房间均以"channel-"开头 // if (!room.startsWith('channel-')) return; // 此处执行创建MongoDB流并存储到数组的逻辑 console.log(`业务房间已创建:${room}`); });
方案2:在socket.join回调中处理
放弃监听create-room事件,改为在socket.join的回调里判断房间是否为新创建(即当前是第一个加入该房间的socket),再执行流创建逻辑:
io.on('connection', async socket => { const channel_id = socket.handshake['query']['channel'] as string; socket.join(channel_id, (err) => { if (err) return; const room = io.of('/').adapter.rooms.get(channel_id); // 房间成员数为1,说明是刚创建的新房间 if (room?.size === 1) { // 此处生成MongoDB流并存储 console.log(`业务房间已创建:${channel_id}`); } }); });
对应删除房间的处理
在deleted-room事件中同样需要过滤非业务房间,避免误关闭流:
io.of('/').adapter.on('deleted-room', (room) => { if (/^[A-Za-z0-9]{16}$/.test(room)) return; // 从数组中取出对应流并关闭 console.log(`业务房间已删除:${room}`); });
内容的提问来源于stack exchange,提问作者Samnan
相关产品推荐
相关产品推荐

