首页 > 解决方案 > 循环遍历独特的 Socket.IO 房间以向 NodeJS 中的每个房间发出独特的数据

问题描述

我通过允许客户传递他们的房间名称来创建房间:

io.on('connection', socket => {
  socket.join(socket.handshake.query.roomName)
})

假设三个套接字连接,房间名称是 1、2 和 3。我希望能够执行以下操作:

listOfRooms.forEach(sendSomeData)

sendSomeData(room, index){
    let data = getSomeData(room)
    io.in(room).emit('data', data)
}

wheregetSomeData(room)根据传递给它的房间名称生成不同的数据。

是否有任何内置方法可以获取根命名空间中所有房间的列表或该 IO 实例的列表,而无需设置数据结构来管理它?

是的,我可以创建一个数组并在每次发生新连接时附加到它,但是如果两个套接字加入同一个房间,似乎需要管理很多额外的工作,我不希望我的数组有重复,但我可以当一个套接字断开连接时,不要同时删除重复项并从数组中删除对象......

标签: node.jssocket.io

解决方案


您可能不想发送到命名空间中所有房间的列表,因为 socket.io 为每个连接的用户创建了一个房间,而您不想发送到所有这些房间。

您可以获得一个包含命名空间中所有房间的对象(作为对象上的属性名称),如下所示:

let roomsObject = io.of("/").adapter.rooms

或者,只需像这样获取所有房间:

let allRooms = Object.keys(io.of("/").adapter.rooms);

因此,您只需要能够分辨哪些房间是您添加的房间,哪些房间是 socket.io 为每个连接的套接字自动添加的房间。我能想到的最简单的方法是让您始终在您创建的任何房间的开头添加一些标记字符,例如下划线。

io.on('connection', socket => {
  socket.join("_" + socket.handshake.query.roomName)
});

当然,在您提到房间名称的任何其他地方,您需要确保它的前面有适当的“_”,或者如果您向用户显示房间名称,那么您需要将其删除。

然后,您可以区分您的房间名称和 socket.io 房间名称:

let myRooms = Object.keys(io.of("/").adapter.rooms).filter(room => room.startsWith("_"));

现在,您可以迭代房间列表:

for (let room of myRooms) {
    io.of("/").to(room).emit(...)
}

注意:在这个答案中,我展示io.of("/")了如何指定要使用的命名空间(因为您明确提到了命名空间对象),但如果您只是使用默认命名空间,您可以只使用io.to("room").emit(...).


推荐阅读