To handle events send to socket in more orginased way, I've made a router. In that router I want to assign each module to specific event. I've assigned event strings and its handlers to "handlers" object. Then I wanted to assign listeners to given socket in a loop. After assignment I listed all events and it handlers in given socket to be clear. Everything seemd to be fine. Unfortunently, it doesnt work. Socket acts like it would assign every event in handlers object to first handler in that object. Handmade verion works fine, but I just cant get it why simple loop fails :/
Here is code of the socketio handling socket by router:
var socketOptions = {transports:['flashsocket', 'websocket', 'htmlfile', 'xhr-polling', 'jsonp-polling']};
var io = socketio.listen(server,socketOptions).on('connection', function (socket) {
streamRouter(io,socket);
});
And here is code of the router. I've wrote how looks handmade version of assigning sockets and how did look like looped verion. Normally, second one is commented.
var handlers = {
"message": require("./message").doAction,
"subscribe": require("./subscribe").doAction
}
exports.handleConnection = function(io,socket) {
//handmade version
socket.on("subscribe", function(msg){
require("./subscribe").doAction(io,socket,msg);
});
socket.on("message", function(msg){
require("./message").doAction(io,socket,msg);
});
//loop version
for( var event in handlers ) {
socket.on(event, function(msg){
handlers[event](io,socket,msg);
});
}
}
I'ld be greatful for any advice where the bug lies. In short time I'll have many handlers and assigning them one by one will be an ugly copying-pasting through many lines of code :/
In your for-in loop, you're constructing functions that are all closed over the same event variable. As a result, when those functions get executed, they will all refer to the same value. Additionally, you're not guarding your for-in loop against prototype members (which may or may not be intended).
Instead, try this:
Object.keys(handlers).forEach(function(event){
socket.on(event, function(msg){
handlers[event](io, socket, msg);
});
});
For your loop to work, you need to create a new scope for each handler:
for( var event in handlers ) {
(function(handler) {
socket.on(event, function(msg){
handler(io,socket,msg);
});
})(handlers[event]);
}
This has to do with scoping: Javascript doesn't create a 'new' event variable for each loop, and by the time the event handler is called, event will be overwritten (and will contain the value it had in the last iteration of the loop).
This page offers more explaination.