将一个函数绑定到多个套接字
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. }); } }
所以,由于你的事件将在以后发生,你的socket
variables总是最后一个集合。
为了防止这种行为,如果使用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中的socket
variables将始终引用作为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函数,您不会遇到函数范围的问题。