NodeJs / expressjs:在回调中运行冗长的代码

时间:2014-09-02 04:39:52

标签: javascript multithreading node.js

回调是异步的,那么这是否意味着如果我在回调中运行一个冗长的计算它不会影响我的主线程?

例如:

function compute(req,res){    // this is called in an expressjs route.
    db.collection.find({'key':aString}).toArray(function(err, items) {
        for(var i=0;i<items.length;i++){      // items length may be in thousands.
            // Heavy/lengthy computation here, Which may take 5 seconds.
        }
        res.send("Done");
    });
}

因此,对数据库的调用是偶然的。这是否意味着回调内的for循环不会阻塞主线程?

如果它是阻塞的,我怎么能以异步的方式执行这些事情呢?

2 个答案:

答案 0 :(得分:1)

在大多数情况下,node.js在单个线程中运行。但是,node.js允许您进行调用,执行由单独线程处理的低级操作(文件读取,网络请求等)。因此,您的数据库调用很可能发生在一个单独的线程上。但是,当数据库调用返回时,我们返回主线程,你的代码将在主线程中运行(阻塞它)。

解决这个问题的方法是启动一个新线程。您可以使用cluster执行此操作。参见:

http://nodejs.org/api/cluster.html

  • 您的主程序将进行数据库调用
  • 当数据库调用完成时,它将调用fork()并启动运行your-calculations.js的新线程并使用任何输入数据向其发送事件
  • your-calculations.js将侦听事件并在处理事件时执行必要的处理
  • your-calculations.js将在完成处理后将事件发送回主线程(它可以发回任何输出数据)
  • 如果主线程需要输出数据,它可以侦听your-calculations.js发出的事件

答案 1 :(得分:1)

如果你不能做或者不想使用线程,你可以用setImmediates拆分长计算。例如(在我的平板电脑上快速写作,所以可能很草率)

function compute(startIndex, max, array, partialResult, callback) {
   var done = false;
   var err = null;
   var stop = startIndex+100;  // or some reasonable amount of calcs...
   if (stop >= max) {
      stop = max;
      done = true;
   }

   // do calc from startIndex to stop, using partialResult as input
   if (done)
      callback(err, result);
   else 
      process.setImmediate ( go look this part up or I'll edit tomorrow)...
       But the idea is you call youself again with start += 100.
}

在每100个计算节点之间有时间处理其他请求,处理其他回调等。当然,如果它们触发另外一个巨大的计算,那么事情就会停滞不前。