2014-09-02 27 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