Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 415
Joseph Chillemi Avatar asked Jun 06 '16 07:06

Joseph Chillemi


2 Answers

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.

like image 115
jfriend00 Avatar answered Oct 17 '22 11:10

jfriend00


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.

like image 1
ShortFuse Avatar answered Oct 17 '22 10:10

ShortFuse