javascript 是否可以在房间中监听加入和离开事件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8391804/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it possible to listen for join and leave events on a room?
提问by lakenen
I want to do something like:
我想做类似的事情:
var room = io.sockets.in('some super awesome room');
room.on('join', function () {
/* stuff */
});
room.on('leave', function () {
/* stuff */
});
This doesn't seem to work. Is it possible?
这似乎不起作用。是否可以?
To illustrate the desired behavior:
为了说明所需的行为:
io.sockets.on('connection', function (socket) {
socket.join('some super awesome room'); // should fire the above 'join' event
});
回答by Michelle Tilley
In Socket.IO, a "room" is really just a namespace, something to help you filter your giant bag of sockets down to a smaller bag of sockets. Calling io.sockets.in('room').on('something')
will cause the event handler to fire for everysocket in the room when the event fires. If that's what you want, something like this should do the trick:
在 Socket.IO 中,“房间”实际上只是一个命名空间,可以帮助您将巨大的套接字包过滤为较小的套接字包。当事件触发时,调用io.sockets.in('room').on('something')
将导致事件处理程序为房间中的每个套接字触发。如果这就是你想要的,这样的事情应该可以解决问题:
var room = io.sockets.in('some super awesome room');
room.on('join', function() {
console.log("Someone joined the room.");
});
room.on('leave', function() {
console.log("Someone left the room.");
});
socket.join('some super awesome room');
socket.broadcast.to('some super awesome room').emit('join');
setTimeout(function() {
socket.leave('some super awesome room');
io.sockets.in('some super awesome room').emit('leave');
}, 10 * 1000);
Important to note is that you'd get the same effect if you (1) got a list of all sockets in a room and (2) iterated over them, calling emit('join')
on each. Thus, you should make sure that your event name is specific enough that you won't accidentally emit it outside the "namespace" of a room.
需要注意的重要一点是,如果您 (1) 获得房间中所有套接字的列表并且 (2) 遍历它们,调用emit('join')
每个套接字,您将获得相同的效果。因此,您应该确保您的事件名称足够具体,以免意外地将其发送到房间的“命名空间”之外。
If you only want to emit/consume a singleevent when a socket joins or leaves a room, you'll need to write that yourself, as, again, a room isn't a "thing" as much as it's a "filter".
如果您只想在套接字加入或离开房间时发出/使用单个事件,则需要自己编写,因为同样,房间不是“事物”,而是“过滤器” .
回答by Blake
I understand this question is old, but for anyone that stumbles upon this via a google search, this is how I'm approaching it.
我知道这个问题很老,但对于通过谷歌搜索偶然发现这个问题的任何人,这就是我接近它的方式。
Joining a room is something that is pretty easy to account for, even though there aren't native events for joining or leaving a room.
加入房间是很容易解释的事情,即使没有用于加入或离开房间的本地事件。
/* client.js */
var socket = io();
socket.on('connect', function () {
// Join a room
socket.emit('joinRoom', "random-room");
});
And for the server-side
而对于服务器端
/* server.js */
// This will have the socket join the room and then broadcast
// to all sockets in the room that someone has joined
socket.on("joinRoom", function (roomName) {
socket.join(roomName);
io.sockets.in(roomName).emit('message','Someone joined the room');
}
// This will have the rooms the current socket is a member of
// the "disconnect" event is after tear-down, so socket.rooms would already be empty
// so we're using disconnecting, which is before tear-down of sockets
socket.on("disconnecting", function () {
var rooms = socket.rooms;
console.log(rooms);
// You can loop through your rooms and emit an action here of leaving
});
Where it gets a bit trickier is when they disconnect, but luckily a disconnecting
event was added that happens before the tear down of sockets in the room. In the example above, if the event was disconnect
then the rooms would be empty, but disconnecting
will have all rooms that they belong to. For our example, you'll have two rooms that the socket will be a part of, the Socket#id
and random-room
当它们断开连接时变得有点棘手,但幸运的disconnecting
是添加了一个事件,该事件发生在拆除房间内的插座之前。在上面的示例中,如果事件是disconnect
那么房间将是空的,但disconnecting
将拥有它们所属的所有房间。对于我们的示例,您将有两个房间,插座将成为其中的一部分,Socket#id
和random-room
I hope this points someone else in the right direction from my research and testing.
我希望这能从我的研究和测试中为其他人指明正确的方向。
回答by siniradam
Recently troubled with the same problem. The code below should be the answer to what you're looking for. It may not be the most elegant solution, but works.
最近被同样的问题困扰。下面的代码应该是您正在寻找的答案。它可能不是最优雅的解决方案,但有效。
The catch is instead of using socket.join("something")
You need to use something like this this.roomHandler.room(socket,"room1","join")
.
问题是而不是使用socket.join("something")
你需要使用这样的东西this.roomHandler.room(socket,"room1","join")
。
class myserver{
constructor(){
this.io = require('socket.io')(85);
this.io.on('connection', (socket) => {
console.log("New User")
this.roomHandler.room(socket,"room1","join")
this.roomHandler.room(socket,"room2","join")
//this.roomHandler.room(socket,"room3","join")
this.roomHandler.room(socket,"room3","leave")
console.log("---")
console.log(this.roomHandler.roomsOfUser)
socket.on('disconnect', (reason) => {
this.roomHandler.disconnect(socket, reason)
console.log(this.roomHandler.roomsOfUser)
})
})
//Room Event Handler Definition
this.roomHandler = {
disconnect:(socket, reason)=>{
if(this.roomHandler.roomsOfUser[socket.id]){
this.roomHandler.roomsOfUser[socket.id].forEach(room => {
this.roomHandler.room(socket, room, "disconnect")
})
delete this.roomHandler.roomsOfUser[socket.id];
}
},
roomEvents : {},
roomsOfUser: {},
room:(socket,room,action)=>{//Join Or Leave
if(typeof socket == "object" && typeof socket.join == "function"){
if(typeof room=="string"){
//Room Join
if(action=="join"){
socket.join(room)
this.roomHandler.roomOn(room,"join",socket)
//Create, append room collection for user
if(this.roomHandler.roomsOfUser[socket.id]){
this.roomHandler.roomsOfUser[socket.id].push(room)
}else{
this.roomHandler.roomsOfUser[socket.id] = [room]
}
//Room Leave
}else if(action == "leave"){
if(this.roomHandler.roomsOfUser[socket.id][room]){//Really in the room?
socket.leave(room)
this.roomHandler.roomOn(room,"leave", socket)
}
//User Disconnected
}else if(action == "disconnect"){
this.roomHandler.roomOn(room,"leave", socket)
}else{
console.log("Undefined room action.")
}
}else{ console.log("Unqualified name for room."); }
}else{ console.error("Not a legit socket object",socket); socket.join("aaa") }
},
roomOn:(room, event, socket)=>{
if (typeof this.roomHandler.roomEvents[room] == "function"){
this.roomHandler.roomEvents[room](event,socket)
}else{
console.log(`No event found for ${room}`, this.roomHandler.roomEvents)
}
},
roomRegister:(room,callback)=>{
if (typeof room == "string" && typeof callback == "function") {
console.log(`Callback registered for ${room}`)
this.roomHandler.roomEvents[room] = callback
}else{
console.log("Room name or callback is invalid.")
}
}
}
//END OF HANDLER
//Register Functions for room events.
this.roomHandler.roomRegister("room1",(event,socket)=>{
console.log(`${event} for room1 BY ${socket.id}`)
})
this.roomHandler.roomRegister("room2",(event,socket)=>{
console.log(`${event} for room2 BY ${socket.id}`)
})
this.roomHandler.roomRegister("room3",(event,socket)=>{
console.log(`${event} for room3 BY ${socket.id}`)
})
}
}
const server = new myserver();
回答by Layke
You can use the native "disconnect" event.
您可以使用本机“断开连接”事件。
socket.on('disconnect', function () {
io.sockets.emit('user disconnected');
});