简体   繁体   English

循环遍历唯一的 Socket.IO 房间以向 NodeJS 中的每个房间发送唯一数据

[英]Loop over unique Socket.IO rooms to emit unique data to each room in NodeJS

I am creating rooms by allowing the client to pass their room name:我通过允许客户传递他们的房间名称来创建房间:

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

Let's just say three sockets connect, and the room names are 1, 2, and 3. I want to be able to do something like:假设三个套接字连接,房间名称为 1、2 和 3。我希望能够执行以下操作:

listOfRooms.forEach(sendSomeData)

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

Where getSomeData(room) generates different data depending on the name of the room passed to it.其中getSomeData(room)根据传递给它的房间的名称生成不同的数据。

Is there any built in way to get a list of all rooms in the root namespace or for that IO instance without setting up a data structure to manage it?是否有任何内置方法可以在不设置数据结构来管理它的情况下获取根命名空间或该 IO 实例中所有房间的列表?

Yes I could just create an array and append to it every time a new connection occurs but it seems like a lot of extra work to manage if two sockets join the same room, I don't want my array to have duplicates, but I can't both get rid of duplicates, and delete the object from the array when one socket disconnects...是的,我可以在每次发生新连接时创建一个数组并附加到它,但是如果两个套接字加入同一个房间,似乎需要很多额外的工作来管理,我不希望我的数组有重复,但我可以当一个套接字断开连接时,不能同时删除重复项并从数组中删除对象...

You probably don't want to send to a list of all rooms in the namespace because socket.io creates a room for every connected user and you don't want to send to all of those.您可能不想发送到命名空间中所有房间的列表,因为 socket.io 为每个连接的用户创建了一个房间,而您不想发送给所有这些用户。

You can get an object that contains all the rooms in a namespace (as property names on an object) like this:您可以获得一个包含命名空间中所有房间的对象(作为对象的属性名称),如下所示:

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

Or, just get all the rooms like this:或者,像这样获得所有房间:

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

So, then you just need to be able to tell which rooms are ones you added and which ones are ones that socket.io added automatically for each connected socket.所以,那么你只需要能够分辨哪些房间是你添加的,哪些是 socket.io 为每个连接的套接字自动添加的。 The simplest way I can think of is for you to always add some sentinel character to the start of any rooms you create such as an underscore.我能想到的最简单的方法是始终在您创建的任何房间的开头添加一些标记字符,例如下划线。

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

And, of course, anywhere else you refer to the room name, you need to make sure it has the appropriate "_" on the front or if you're showing room names to the user, then you need to remove it.而且,当然,在您提到房间名称的任何其他地方,您需要确保其前面有适当的“_”,或者如果您向用户显示房间名称,则需要将其删除。

Then, you can tell the difference between your room names and the socket.io room names:然后,您可以分辨房间名称和 socket.io 房间名称之间的区别:

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

Now, you can iterate that list of rooms:现在,您可以迭代该房间列表:

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

Note: in this answer, I showed io.of("/") to indicate how you specify the namespace you want to use (because you explicitly mentioned a namespace object), but if you're just using the default namespace, you can just to io.to("room").emit(...) .注意:在这个答案中,我展示了io.of("/")来指示您如何指定要使用的命名空间(因为您明确提到了命名空间对象),但是如果您只是使用默认命名空间,则可以只是到io.to("room").emit(...)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM