知道事件名称的事件处理程序

时间:2013-05-02 11:16:47

标签: javascript asynchronous scope

我有一个生成许多事件的socket.io服务器,我想要捕获所有这些事件并打印类似的消息。现在,我这样做:

for (var event in {eventA: 1, eventB: 1, eventC: 1}) {
    this.translationSocket.on(event, function(result) {
        console.log("Server sent an event of type "+event);
    });
}

当服务器发送eventA,eventB和eventC时,我看到:

Server sent an event of type eventC
Server sent an event of type eventC
Server sent an event of type eventC

即。我的程序捕获所有事件,但始终显示eventC的类型...

我尝试了以下变体:

  • 删除“for”中的“event”之前的“var”:“for(event ...”
  • 添加语句'var msg =“服务器发送了类型为”+ event;“的事件或者在'on'语句之前或者在'console.log'语句之前,然后是'console.log(msg)'。

这些变化都没有奏效......

我该怎么办?

3 个答案:

答案 0 :(得分:1)

这与socket.io或node.js无关,这是众所周知的JavaScript“quirk”。执行代码时会计算event的值,即循环结束时。您需要将thing包装到函数调用中以保留该值。

var listen = function(socket, event) {
    socket.on(event, function(result) {
        console.log("Server sent an event of type "+event);
    });
}


for (var event in {eventA: 1, eventB: 1, eventC: 1}) {
    listen(event);
}

或(较短版本):

for (var event in {eventA: 1, eventB: 1, eventC: 1}) {
    (function(event) {
        this.translationSocket.on(event, function(result) {
            console.log("Server sent an event of type "+event);
        });
    })(event);
}

答案 1 :(得分:1)

for (var event in ...)中,您声明了一个变量,并且由于 JavaScript 中的变量范围规则,它将在foreach循环之外有效。

event变量在循环结束时变为eventC。 所以它的价值在于,当您想要打印时,它将是eventC

您可以这样做:

function generateCallback(e, result) {
    return function () {
        console.log("Server sent an event of type " + e);
    };
}

var e;
// ...
for (e in {eventA: 1, eventB: 1, eventC: 1}) {
    this.translationSocket.on(e, generateCallback(e, result));
}

防止混淆you'd better not to declare variables in for statements

而且它也更好,not to make functions within a loop。这就是我使用generateCallback而不是在循环中创建回调函数的原因。

答案 2 :(得分:0)

我会在npm上使用socket.io-events。您可以捕获所有事件并根据需要处理它们,而无需绑定单独的处理程序。

var io = require('socket.io')(3000);
var router = require('socket.io-events')();
 router.on('*', function (sock, args, next) {
 var name = args.shift(), msg = args.shift();
 sock.emit('received event', name, msg);
});
io.use(router);