2014-09-02 66 views
0

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

例如:

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"); 
    }); 
} 

所以,在调用数据库ascnchronous。这是否意味着回调中的for循环不会阻塞主线程?

如果它阻塞,我该如何以异步的方式执行这样的事情?

+1

回调*在你的主线程中 - node.js *只有一个线程*。任何时候,如果您在node.js中花费了几毫秒而不将其委托给另一个进程,那么您应该感觉不好。 :) – Amadan 2014-09-02 04:44:10

+0

是的,我感觉如此,但是不能做任何事情吗?其实我夸大了5秒。但是,有时需要一些处理。 – codin 2014-09-02 04:50:19

回答

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发出
+0

看起来像一个解决方案,我将不得不先阅读。 Thankyou – codin 2014-09-02 05:08:38

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个计算节点有时间来处理其他请求之间,处理其它回调,等等。当然,如果他们触发另外一个巨大的计算evedntually事情会停下来。

+0

当然,我会检查process.setImmediate。谢谢。 – codin 2014-09-02 05:53:18