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

io.on('connection', function(socket) { socket.join('myRoom'); if(condition){ bindFunctions(); } }); 

假设第四个sockets连接时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的套接字。 我会认为处理程序套接字应该是相同的function内的套接字。

所以我有两个问题:

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

我可以做什么,而不是在函数内部访问名为'my event'的套接字的属性?

发生这种情况,因为虽然你正在做var socket = io.sockets.connected[socketId]; 在循环内部, 在Javascript中, var关键字是函数作用域 ,而不是作用域的作用域。

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

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

所以,由于你的事件将在以后发生,你的socketvariables总是最后一个集合。

为了防止这种行为,如果使用Node.js版本> 4.0.0,则可以使用const而不是var ,因为它的作用域是作用域的 。 但是在Node.js中,为了能够使用const并且let关键字为block-scoped,你必须把'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. }); } } 

解决你的问题的另一种方法是创build一个IIFE,所以你总是将当前variables传递给事件,例如:

 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中的socketvariables将始终引用作为parameter passing的对象,并且您将获得所需的行为。


你也可以使用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); }); }); } 

这样做,每次迭代都会创build一个新的上下文,因为这是一个被调用的callback函数,您不会遇到函数范围的问题。