Search code examples
node.jswebsocketws

How to attach extra data to a WebSocket connection so I can do clean up on disconnect


I am using npm ws as my WebSocket server using this implementation:

const fs = require("fs");
const https = require("https");
const WebSocket = require("ws");

const server = https.createServer({
  cert: fs.readFileSync("./cert.pem"),
  key: fs.readFileSync("./key.pem"),
});
const wss = new WebSocket.Server({ server, clientTracking: true });

And here are my listeners:

wss.on("connection", function connection(ws) {
  console.log("connection");

  ws.on("close", function close(ws) {
    console.log("disconnect");
  });

  ws.on("message", function incoming(message) {
    console.log("INBOUND MESSAGE: %s", message);
    obj = JSON.parse(message);

    switch (obj.action) { ....

I am using the socket server to set up a card game. I am able to attach the ws connection coming from on("message to an object (e.g., player[id].ws = ws) and I'm able to use that attached data to send messages (e.g., ws.send(player[id].ws, ____);)

The challenge I have is when a connection drops, I need to clean up all the game data surrounding the player, (game data, player data, etc). However, when the "close" listener fires, the ws data does not have any data in it so I can identify who dropped and clean up the data?

I would like to be able to on("message" set ws.playerId='ksjfej so when I get the ws("close" I can use ws.playerId to clean up.


Solution

  • Perhaps you don't realize, but inside the close event the ws variable that represents the connection is entirely within scope as long as you remove the ws parameter you mistakenly declared from the callback. So, this will work.

    wss.on("connection", function connection(ws) {
      console.log("connection");
    
      // change this callback signature to remove the `ws`
      ws.on("close", function(/* no ws here */) {
        console.log("disconnect");
        // you can reference the `ws` variable from a higher scope here
        // you just have to remove it from the function parameter list here
        // because it isn't passed to the event itself.
        console.log(ws);   // this will get ws from the higher scope
      });
    });