将函数绑定到多个套接字

时间:2015-11-09 11:45:27

标签: javascript node.js socket.io

io.on('connection', function(socket) {

    socket.join('myRoom');
    if(condition){
        bindFunctions();
    }

});

当第4个套接字连接时,让我们说condition为真。下面的代码成功地将.on处理程序绑定到myRoom中的所有套接字。

bindFunctions(){
    for(var socketId in io.sockets.adapter.rooms["myRoom"]){

        var socket = io.sockets.connected[socketId];

        socket.on('my event',function(submit){
            console.log(socket.myVariable);
            //This is always the same property, no matter who calls this function.      

        }); 
    }
}

但是,当'my event'触发时,无论哪个客户端触发它,socket对象始终是连接的第4个套接字。始终是调用bindFunctions的套接字。我原以为处理程序套接字应该与函数内的套接字相同。

所以我有两个问题:

为什么'my event'函数内的套接字是调用bindFunctions的套接字而不是触发事件的套接字?

我可以做些什么来在函数内部访问调用'my event'的套接字的属性?

1 个答案:

答案 0 :(得分:2)

之所以会发生这种情况,是因为虽然你在循环中var socket = io.sockets.connected[socketId];进行了bindFunctions(){ var socket; for(var socketId in io.sockets.adapter.rooms["myRoom"]){ socket = io.sockets.connected[socketId]; socket.on('my event',function(submit){ console.log(socket.myVariable); //This is always the same property, no matter who calls this function. }); } } ,但没有阻止作用域。

根据胆量,真正发生的事情是:

socket

因此,由于您的事件将在稍后发生,因此您的const变量始终是最后一个变量。

要防止此行为,请使用Node.js版本> 4.0.0,您可以使用in Javascript, the var keyword is function scoped。但是在Node.js中,为了能够使用块范围的let'use strict';关键字,必须将bindFunctions(){ 'use strict'; for(var socketId in io.sockets.adapter.rooms["myRoom"]){ const socket = io.sockets.connected[socketId]; socket.on('my event',function(submit){ console.log(socket.myVariable); //This is always the same property, no matter who calls this function. }); } } 放在函数的开头,例如:

bindFunctions(){
    for(var socketId in io.sockets.adapter.rooms["myRoom"]){

        var socket = io.sockets.connected[socketId];

        (function(socket) {
            socket.on('my event',function(submit){
                console.log(socket.myVariable);
            });
        })(socket);
    }
}

解决问题的另一种方法是创建一个IIFE,因此你总是将当前变量传递给事件,例如:

socket

这样做,IIFE中的Object.keys变量将始终引用作为参数传递的对象,并且您将获得所需的行为。

您还可以使用Array.prototype.forEach结合for...in代替bindFunctions(){ var room = io.sockets.adapter.rooms["myRoom"]; Object.keys(room).forEach(function(key) { var socketId = room[key]; var socket = io.sockets.connected[socketId]; socket.on('my event',function(submit){ console.log(socket.myVariable); }); }); } 循环:

{{1}}

这样做,你每次迭代都会创建一个新的上下文,因为它是一个被调用的回调函数,你不会遇到函数作用域的问题。