Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/423.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将函数绑定到多个套接字_Javascript_Node.js_Socket.io - Fatal编程技术网

Javascript 将函数绑定到多个套接字

Javascript 将函数绑定到多个套接字,javascript,node.js,socket.io,Javascript,Node.js,Socket.io,假设第四个插座连接时,条件为真。下面的代码成功地将.on处理程序绑定到myRoom中的所有套接字 io.on('connection', function(socket) { socket.join('myRoom'); if(condition){ bindFunctions(); } }); 但是,当'my event'触发时,无论是哪个客户端触发了它,socket对象始终是连接的第四个套接字。调用bindFunctions的总是套接字。我认为处

假设第四个插座连接时,
条件
为真。下面的代码成功地将
.on
处理程序绑定到
myRoom
中的所有套接字

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

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

});
但是,当
'my event'
触发时,无论是哪个客户端触发了它,
socket
对象始终是连接的第四个套接字。调用
bindFunctions
的总是套接字。我认为处理程序套接字应该与函数中的套接字相同

所以我有两个问题:

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


我可以做些什么来代替在函数内部访问调用“我的事件”的套接字的属性?

这是因为尽管您正在执行
var socket=io.sockets.connected[socketId]在循环内,且不在块范围内

在勇气之下,真正发生的是:

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.      

        }); 
    }
}
因此,由于事件将在稍后发生,因此
socket
变量始终是最后一组

为了防止这种行为,如果使用Node.js version>4.0.0,可以使用。但是在Node.js中,为了能够使用
const
let
关键字阻塞范围,必须将
设置为“使用严格”在函数的开头,例如:

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.      

        }); 
    }
}

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

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.      

        }); 
    }
}
这样,IIFE中的
socket
变量将始终引用作为参数传递的对象,您将获得所需的行为


您还可以将
Object.keys
Array.prototype.forEach
结合使用,而不是
用于循环中的…:

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);
    }
}

这样,每次迭代都会创建一个新的上下文,因为它是一个被调用的回调函数,并且在函数作用域方面不会有问题。

为什么不在函数连接后直接将其绑定到套接字?比如
io.on('connection',function(socket){socket.join('myroom');socket.on('myevent',function…)
然后你可以检查绑定函数内的条件……这样你就不必在套接字上循环。可能最好使用
,不?const
不是代表一个不变的变量吗?@JonathanBrooks因为他在循环内创建
套接字
,并且从不改变它,理论上是一个变量
const
变量。如果您使用一些linter,例如:ESLint,它将发出警告,尽管您使用的是
let
,但您永远不会更改它的值。非常感谢@Buzinas:)还有,有关“变量提升”的更多信息,请参阅伟大的答案,谢谢!也谢谢你的文章@JonathanBrooks
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);    
        }); 
    });
}