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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 16:15:11