socket.io, adding message handler dynamically

2020-07-18 09:39发布

问题:

I've written happily a node.js server, which uses socket.io to communicate with the client. this all works well. the socket.on('connection'...) handler got a bit big, which made me think of an alternative way to organize my code and add the handlers in a generator function like this:

sessionSockets.on('connection', function (err, socket, session) {
  control.generator.apply(socket, [session]);
}

the generator takes an object that contains the socket events and their respective handler function:

var config = {
  //handler for event 'a'
  a: function(data){
    console.log('a');
  },

  //handler for event 'b'
  b: function(data){
    console.log('b');
  }
};


function generator(session){

  //set up socket.io handlers as per config
  for(var method in config){
    console.log('CONTROL: adding handler for '+method);

    //'this' is the socket, generator is called in this way
    this.on(method, function(data){
      console.log('CONTROL: received '+method);
      config[method].apply(this, data);
    });
  }
};

I was hoping that this would add the socket event handlers to the socket, which it kind of does, but when any event comes in, it always calls the latest one added, in this case always the b-function.

Anyone any clues what i am doing wrong here?

回答1:

The problem appears because by that time this.on callback triggers (let's say in a few seconds after you bind it), the for loop is finished and method variable becomes the last value.

To fix that you may use some JavaScript magic:

//set up socket.io handlers as per config
var socket = this;
for(var method in config){
  console.log('CONTROL: adding handler for '+method);

  (function(realMethod) {
    socket.on(realMethod, function(data){
      console.log('CONTROL: received '+realMethod);
      config[realMethod].apply(this, data);
    });
  })(method);  //declare function and call it immediately (passing the current method)
}

This "magic" is hard to understand when you first see it, but when you get it, the things become clear :)