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'
的套接字的属性?
答案 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}}
这样做,你每次迭代都会创建一个新的上下文,因为它是一个被调用的回调函数,你不会遇到函数作用域的问题。