对于回调中的循环。阻止?

时间:2014-02-25 00:21:06

标签: node.js mongoose

//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循环,可以很长(results.length = 100)。

我是否写过阻止代码?如果是,我怎样才能使其无阻塞?

1 个答案:

答案 0 :(得分:3)

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

长篇故事:

JavaScript(和Node因此)是单线程的。在这个问题的上下文中意味着什么 - 当你循环运行时,不能调用其他函数。 解除阻止的唯一方法是使用子进程。你有两种选择,每种都有它自己的力量和缺点。

  1. 运行群集,以便在“阻止”一个节点进程时,您有另一个进程来处理传入的请求。
  2. 生成一个子进程,为您运行一些繁重的东西,然后报告结果。
  3. 第一个选项非常简单,需要您将服务器包装在群集http://nodejs.org/api/cluster.html中 但是,您可能会在每个节点进程中运行此循环来“阻止”整个集群。

    第二种选择实施起来更复杂,需要更多资源。但是,当你必须做一些非常沉重和/或可能存在内存泄漏的事情时,这真是令人惊讶。这允许你做的是创建一个单独的Node进程(需要一些RAM并花费几毫秒才能启动,所以你不能产生数百万这些人),传递一些参数并等待结果来。您的父进程将能够提供即将发出的请求。但是一旦完成,不要忘记杀死子进程。 http://nodejs.org/api/child_process.html

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

    P.S。反向循环运行得更快:

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