Joseph Chillemi
Joseph Chillemi

Reputation: 188

Adding a variable to sockets in socket.io

I wanted to associate an object called player to different sockets. So I thought the easiest way to do that is to just socket.prototype.player = whatever;

But no matter what I try to prototype I keep getting undefined. Anyone have an idea on how to accomplish this ? Also IDK if this is bad practice. Let me know.

Upvotes: 9

Views: 11861

Answers (4)

www-data
www-data

Reputation: 244

You can also handle online users pairing them with their socket id like this

io.on('connection', function(socket){
  socket.on('disconnect', function() {
    console.log("disconnect")
    for(var i = 0; i < onlineplayers.length; i++ ){
      if(onlineplayers[i].socket === socket.id){
        console.log(onlineplayers[i].code + " just disconnected")
        onlineplayers.splice(i, 1)
      }
    }
    io.emit('players', onlineplayers)
  })

  socket.on('lobby_join', function(player) {
    if(player.available === false) return
    var exists = false
    for(var i = 0; i < onlineplayers.length; i++ ){
      if(onlineplayers[i].code === player.code){
        exists = true
      }
    }
    if(exists === false){
      onlineplayers.push({
        code: player.code,
        socket:socket.id
      })
    }
    io.emit('players', onlineplayers)
  })

  socket.on('lobby_leave', function(player) {
    var exists = false
    for(var i = 0; i < onlineplayers.length; i++ ){
      if(onlineplayers[i].code === player.code){
        onlineplayers.splice(i, 1)
      }
    }
    io.emit('players', onlineplayers)
  })
})

Upvotes: 1

ShortFuse
ShortFuse

Reputation: 6824

Since you did ask about best practices, it's not advised to modify the prototype of the type that's not in your control or use custom variables on top of it. While JavaScript is rather loose and lets you make these changes, you should guard yourself against any further changes to the prototype that Socket.IO may make in the future.

The reason is that there's always a chance, however small, of there being a collision with whatever property name you're using.

To get around this, we can either use a Map related to the socket ID, or use a WeakMap on the socket itself. If you use a Map, you have to remove the entry manually when the socket is disconnected, but with a WeakMap, it's garbage collected automatically (assuming SocketIO releases all references to it on disconnect).

  /** @type {WeakMap<SocketIO.Socket, Object>} */
  const socketIOLocals = new WeakMap();
  io.use((socket, next) => {
      const locals = { player: null }; // Create new instance
      socketIOLocals.set(socket, locals);
      next();
  });

You can then get the variable object with socketIOLocals.get(socket);


On a side note, Express does have the .locals property to let you pass data between Response objects. It's a shame SocketIO doesn't have something like this.

Upvotes: 2

cyphunk
cyphunk

Reputation: 169

Solution as of Dec 2017 (socket.io innards changes more often than one might assume). In this version I've created a join_exclusive function which will leave all rooms, except the default room and the new room you want to join

io.sockets.on('connection', function(socket) {
    socket.join_exclusive = function (newroom) {
        for (var room in this.manager.roomClients[this.id]) {
            if (room == '') continue; // default room required for socket.emit(...
            this.leave(room.slice(1)); // remove '/' char
        }
        this.join(newroom);
    };
});

Upvotes: 0

jfriend00
jfriend00

Reputation: 708046

A socket.io socket is just a Javascript object. You can add any property to it directly, not through the prototype.

So, on the server, you could just add a new property to the socket object directly:

io.on('connection', function(socket) {
    // some code to get the name for this user
    var name = .....
    socket.player = name;
});

Properties like this are not shared with the other end of the connection - they are local to this particular object and are only available on this side of the connection.

Upvotes: 20

Related Questions