简体   繁体   中英

Most efficient way to store and access list of clients in Sockets.IO Node.JS

I'm having this simple socket.io manager, where when a user connects, he will be added to a pool of online clients and when another client (say client B), sends a message to client A, It should try to send that message only if client is in the pool. Currently I have this:

var connectionMap = [];
const socketHandler = (io) => {
  io.on("connection", (socket) => {
    socket.id = "some_custom_id I define";
    connectionMap.push(socket);

    socket.on("textMessage", function (message) {
      connectionMap.forEach(function (connection, index) {
        if (connection.id == message.receiver_id)
          connection.emit("textMessage", message);
      });
    });

    socket.on("disconnect", function () {
      connectionMap.splice(connectionMap.indexOf(client), 1);
    });
  });
};

Although this might work on a use case with small number of users, I'm looking for a solution that could scale decently without throttling the performance much. (I can't imagine a foreach running across thousands of indexes on every message sent accross the platform.) Any ideas on how to approach this?

You can use an object instead of an array for connectionMap . On connection we set the socket.id as key in the object and value can be true . During message we can check directly in connectionMap if message.receiver_id is present. This is a significant improvement over using array as connectionMap because in the worst case array will take O(N) time and with object (map) you can have constant time O(1)

var connectionMap = {};
const socketHandler = (io) => {
  io.on("connection", (socket) => {
    socket.id = "some_custom_id I define";
    connectionMap[socket.id] = socket;

    socket.on("textMessage", function (message) {
        if (connectionMap[message.receiver_id]) {
            connectionMap[message.receiver_id].emit("textMessage", message);
        }
    });

    socket.on("disconnect", function () {
        delete connectionMap[client];
    });
  });
};

Or you can use a Map

var connectionMap = new Map();
const socketHandler = (io) => {
  io.on("connection", (socket) => {
    socket.id = "some_custom_id I define";
    connectionMap.set(socket.id, socket);

    socket.on("textMessage", function (message) {
        if (connectionMap.has(message.receiver_id)) {
          connectionMap.get(message.receiver_id).emit("textMessage", message);
        }
    });

    socket.on("disconnect", function () {
        connectionMap.delete(client);
    });
  });
};

Use an Object instead of Array , so you can access sockets directly by id instead of having to search through them until you find the one you want:

 const connectionMap = {}; const socketHandler = io => { io.on('connection', socket => { socket.id = 'some_custom_id I define'; connectionMap[socket.id] = socket; socket.on('textMessage', message => { connectionMap[message.receiver_id].emit('textMessage', message); }); socket.on('disconnect', message => { delete connectionMap[socket.id]; }); }); };

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