socket.io使用for循环添加socket.on方法

时间:2012-10-19 07:18:00

标签: javascript node.js sockets socket.io

假设

socketMethods:{
    update:function(data){
        this.emit("test", data);
        console.log("socket.update");
    },
    test:function(data){
        this.emit("test", data);
        console.log("socket.test");
    }
}

以下是可能的,并允许我发出“测试”和“更新”,并将调用“测试”和“更新”

socket.on("test", function(data){
    dummy.socketMethods.test.call(socket, data);
});
socket.on("update", function(data){
    dummy.socketMethods.update.call(socket, data);
});

以下这些是不可能的......如果我发出“test”或“update”,每个人都会调用“test”。如果我使用FOR循环,所有方法都将成为名为的“最后”方法。

即:如果我切换更新并测试以便测试是第一个,并且更新在socketMethods对象中是第二个。无论我是否要求“测试”或“更新”

,都会始终调用“更新”
for(key in dummy.socketMethods){
    socket.on(key, function(data){
        dummy.socketMethods[key].call(socket, data);
    });
}



var methods = ["test", "update"];
while(methods.length !== 0){
    var method = methods.pop();
    console.log(method);
    socket.on(method, function(data){
        dummy.socketMethods[method].call(socket, data);
    });
}



var methods = ["test", "update"];
for(var i = 0; i < methods.length; i++){
    console.log(i);
    socket.on(methods[i], function(data){
        console.log(i);
        dummy.socketMethods[methods[i]].call(socket, data);
    });
}

CLUE:使用'i'的for循环有两个console.logs。第二个console.log返回“2”

为什么会这样?我怎么能用for循环来连接我的socketMethods?

1 个答案:

答案 0 :(得分:5)

你犯了一个常见的错误,就是假设一个闭包在“创建时”捕获外部函数变量的。它没有。它将引用“捕获”到外部函数的变量,其值将是闭包执行时外部变量所具有的值。如果你在循环中创建闭包,那么该值将是循环结束时的任何值。

解决这个问题的方法是创建一个“封闭”闭包,它使用外部变量的值作为参数。一种方法是创建一个生成闭包的辅助函数。在您的第一个示例中,您可以执行

function makeOn(key) {
  return function(data) {
    dummy.socketMethods[key].call(socket, data);
  }
}

for(key in dummy.socketMethods){
  socket.on(key, makeOn(key));
}

现在在每个闭包中,key将是一个新创建的变量(闭包之间不同)设置为适当的值。

也可以使用立即函数调用(有些人称之为“自动执行函数”)来更简洁地执行相同的操作,但也可能不太可读。