2014-02-25 111 views
2
//defining schemas, models, db connections, etc.. 

http.createServer(function (req, res) { 
    // some irrelevant stuff.. 

    Model.find({name : regex}).exec(function (err, results) { 

    var localArray = []; 

    for (var i = 0, len = results.length; i < len; ++i) { 
     localArray.push(results[i].name); 
     localArray.push(results[i].id); 
    }; // is this for loop blocking? 

    // some more irrelevant stuff.. 
    }); 
}).listen(8080); 

我的回调函数有一个可以很长的for循环(有时候结果长度= 100)。For循环回调。阻止?

我写了封锁代码吗?如果是的话,我怎样才能让它无阻塞?

+2

它是循环阻塞,但它不阻止I/O。如果你需要的话,这很好。 100项不足以打扰循环或JS。 –

+0

感谢您的快速回复。 :) –

+0

而你错过了response.json(localArray); :) – Zlatko

回答

2

为了长话短说,答案是肯定的,它是封锁。此循环运行时收到的任何请求都将排队。使用子进程来解锁你的父代码。它需要你机器成为多核(不是产生一个过程,而是高效)。

长篇小说:

JavaScript(和Node因此)是单线程的。这个问题的意义是什么 - 当你的循环运行时,没有其他函数可以被调用。 解锁它的唯一方法是使用子进程。你有两种选择,每种都有自己的力量和缺点。

  1. 运行一个群集,以便当一个节点进程“被阻塞”时,您有另一个进程来处理传入的请求。
  2. 产生一个子进程来运行一些重要的东西,然后报告结果。

第一个选项是非常简单的,需要你来包装你的服务器集群http://nodejs.org/api/cluster.html 但是有机会,你“块”整个集群的每个节点进程中运行这个循环。

第二种方法实施起来比较复杂,需要更多的资源。但是,当你必须做一些非常重的和/或可能会导致内存泄漏的事情时,这是惊人的。这可以让你做的是创建一个单独的节点进程(这将需要一些内存,并需要几毫秒的时间来启动,所以你不能产生数百万这些家伙),传递一些参数,并等待结果来。您的父母程序将能够提供即将到来的请求。但是,一旦完成,不要忘记杀死子进程。 http://nodejs.org/api/child_process.html

无论你选择什么,请注意,你仍然在同一台机器上运行,你遇到的下一个瓶颈是你的机器资源。无论如何运行一些基准。迭代超过一百个项目并不会产生一个孩子那么重,但是如果您迭代数千或更多?...

p.s.反转循环运行得更快:

for (var i = results.length; i > 0; i--) { 
    //Do something 
};