skip to Main Content

Suppose the following:

const socketTracker = new Map();

const addToSocketTracker = ({ userId, socketId }) => {
  socketTracker.set({
      socketId,
      userId
  }, {
      sendMessage: function() {
        return [`Socket ID: ${this.socketId}`, `User ID: ${this.userId}`].join('n')
      }
  });
}

addToSocketTracker({ userId: 123, socketId: 456 })

const element = socketTracker.get(({ userId }) => userId === 123); // this returns undefined
element?.sendMessage();

console.log('element', element);

Is it possible to access a specific key and then call sendMessage as in the snippet?

3

Answers


  1. const socketTracker = new Map();
    
    const addToSocketTracker = ({ userId, socketId }) => {
      socketTracker.set({
          socketId,
          userId
      }, {
          sendMessage: function() {
            return [`Socket ID: ${this.socketId}`, `User ID: ${this.userId}`].join('n')
          }
      });
    }
    
    addToSocketTracker({ userId: 123, socketId: 456 })
    
    const element = socketTracker.get(({ userId }) => userId === 123); // this returns undefined
    element?.sendMessage();
    
    console.log('element', element);
    Login or Signup to reply.
  2. Is it possible to access a specific key and then call sendMessage?

    It is, but it’s not efficient. You have to loop through the map’s keys:¹

    const key = [...socketTracker.keys()].find(({ userId }) => userId === 123);
    const element = key ? socketTracker.get(key) : undefined;
    element?.sendMessage();
    

    In the given example, though, I don’t see any reason for socketId to be part of the key of the map. Fundamentally, key a map by what you’re going to use to look up its entries: just userId, in this case. If you also need to look up entries by socketId, you can have a separate map for that. Or if you need a compound key, you can use a map of maps.

    In particular, it doesn’t make sense to key a map by an object unless you will later have a reference to that same object to use to look up the map entry, since Object.is({}, {}) is false — no object is equal to any other object.


    A couple of notes on that:

    1. You can avoid the intermediate array by writing a simple utility function to do a find-like operation on an iterable. Iterables are getting find, though: https://github.com/tc39/proposal-iterator-helpers.

    2. And I guess technically you don’t need that conditional operator if you never use undefined as a key, just const element = socketTracker.get(key); would also work, giving you undefined for element when key was undefined.

    Login or Signup to reply.
  3. socketTracker.get(({ userId }) => userId === 123) – you are trying to get element like with an Array::filter(). Map::get() actually accepts a key, not a callback.

    Map() isn’t good for this scenario, use Array():

    const socketTracker = [];
    
    const addToSocketTracker = ({ userId, socketId }) => {
      socketTracker.push({
          socketId,
          userId,
          sendMessage: function() {
            console.log( [`Socket ID: ${this.socketId}`, `User ID: ${this.userId}`].join('n'));
          }
      });
    }
    
    addToSocketTracker({ userId: 123, socketId: 456 })
    
    socketTracker.filter(({ userId }) => userId === 123).forEach(socket => socket.sendMessage());

    Basically you are trying to use denormalized data where you have users with sockets. So better restructure (normalize) your data and make sockets as a part of a user object:

    const socketTracker = new Map;
    
    const addToSocketTracker = ({ userId, socketId }) => {
      let user = socketTracker.get(userId);
      if(!user){
        socketTracker.set(userId, {
          sockets:[socketId], 
          sendMessage: function() {
            this.sockets.forEach(socket => console.log( [`Socket ID: ${socket}`, `User ID: ${userId}`].join('n')));
          }
        });
      } else {
        user.sockets.push(socketId);
      }
      
    }
    
    addToSocketTracker({ userId: 123, socketId: 456 })
    
    socketTracker.get(123).sendMessage();
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search