在循环内使用setTimeout不允许阻塞

时间:2014-10-17 12:39:05

标签: javascript node.js websocket settimeout

一些代码行可以让您了解我想要问的内容。 代码以

开头
var webSocketsServerPort = 8002;
var webSocketServer = require('websocket').server;
var conns = [];

我使用数组conns在每次成功连接后推送用户。我把其他(他们的ID)信息放在那里,以便我可以识别用户。

当我需要向用户发送特定信息时,我会调用以下函数。

function sendMessage(userID, message){
    for(var i = 0, len = conns.length; i < len; ++i){
        if(conns[i].customData.ID == userID){
            conns[i].sendUTF(message);
        }
    }
}


我的问题是: 如果用conns[i].sendUTF(message);替换setTimeout(function(){conns[i].sendUTF(message)},1)是一个更好的主意,那么万一有5000个连接用户sendUTF(msg)将无法阻止循环,在最好的情况下,所有消息都将是同时发送。

3 个答案:

答案 0 :(得分:1)

这对你的思维方式没有帮助。如果它没有去&#34;阻止&#34;在那个时候,它会&#34;阻止&#34;在1毫秒。

答案 1 :(得分:1)

以这种方式执行setTimeout只会延迟执行,而不会延迟排队。 JS仍然会阻塞运行你的for循环,以便在清除堆栈之前将所有5000个项目放入等待队列中。

您需要的是让每次迭代都让步。由于您使用的是NodeJS,因此可以使用process.nextTick()来安排下一次迭代。这是一个简单的例子。

var i = 0;
var length = cons.length;

function foo(){
  // if not yet the limit, schedule the next
  if(i++ < length) process.nextTick(foo);

  // Run as usual
  if(conns[i].customData.ID == userID) conns[i].sendUTF(message);

}

答案 2 :(得分:1)

如果您将设计更改为按ID而不是对象数组排序所有内容,则没有理由必须循环查找所有用户的连接。您只需要为每个用户循环遍历多个连接。

var connections = {};
function addConnection (userId, conn) { 
    if (!connections[userId]) {
        connections[userId] = [];
    }
    connections[userId].push(conn);
}

var getUserConnections (userId) {
    return connections[userId];
}