简体   繁体   中英

Is it possible to listen for join and leave events on a room?

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
});

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 every socket in the room when the event fires. If that's what you want, something like this should do the trick:

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.

If you only want to emit/consume a single event 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".

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

I hope this points someone else in the right direction from my research and testing.

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") .

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();

You can use the native "disconnect" event.

socket.on('disconnect', function () {

        io.sockets.emit('user disconnected');
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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