亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

協調node.js中的并行執行

協調node.js中的并行執行

收到一只叮咚 2019-08-06 14:15:45
協調node.js中的并行執行node.js的事件驅動編程模型使得協調程序流有點棘手。簡單的順序執行變成了嵌套的回調,這很容易(雖然寫下來有點復雜)。但并行執行怎么樣?假設您有三個可以并行運行的任務A,B,C,當它們完成時,您希望將結果發送到任務D.使用fork / join模型,這將是叉子A.叉子B.叉子C.加入A,B,C,運行D.我如何在node.js中編寫它?有沒有最佳做法或烹飪書?我是否每次都必須手動滾動解決方案,或者是否有一些帶幫助程序的庫?
查看完整描述

3 回答

?
至尊寶的傳說

TA貢獻1789條經驗 獲得超10個贊

在node.js中沒有什么是真正的并行,因為它是單線程的。但是,可以按照您無法事先確定的順序安排和運行多個事件。而數據庫訪問等實際上是“并行”的,因為數據庫查詢本身在不同的線程中運行,但在完成時會重新集成到事件流中。

那么,如何在多個事件處理程序上安排回調?嗯,這是瀏覽器端javascript動畫中使用的一種常用技術:使用變量來跟蹤完成情況。

這聽起來像是一個黑客,它聽起來可能是混亂的,留下一堆全局變量圍繞著跟蹤,而用較少的語言。但在javascript中我們可以使用閉包:

function fork (async_calls, shared_callback) {
  var counter = async_calls.length;
  var callback = function () {
    counter --;
    if (counter == 0) {
      shared_callback()
    }
  }

  for (var i=0;i<async_calls.length;i++) {
    async_calls[i](callback);
  }}// usage:fork([A,B,C],D);

在上面的例子中,我們通過假設async和callback函數不需要參數來保持代碼簡單。您當然可以修改代碼以將參數傳遞給異步函數,并讓回調函數累積結果并將其傳遞給shared_callback函數。


補充答案:

實際上,即使是這樣,該fork()函數也可以使用閉包將參數傳遞給異步函數:

fork([
  function(callback){ A(1,2,callback) },
  function(callback){ B(1,callback) },
  function(callback){ C(1,2,callback) }],D);

剩下要做的唯一事情是累積A,B,C的結果并將它們傳遞給D.


更多補充答案:

我無法抗拒。在早餐期間一直想著這個。這fork()是累積結果的實現(通常作為參數傳遞給回調函數):

function fork (async_calls, shared_callback) {
  var counter = async_calls.length;
  var all_results = [];
  function makeCallback (index) {
    return function () {
      counter --;
      var results = [];
      // we use the arguments object here because some callbacks 
      // in Node pass in multiple arguments as result.
      for (var i=0;i<arguments.length;i++) {
        results.push(arguments[i]);
      }
      all_results[index] = results;
      if (counter == 0) {
        shared_callback(all_results);
      }
    }
  }

  for (var i=0;i<async_calls.length;i++) {
    async_calls[i](makeCallback(i));
  }}

這很容易。這fork()非常通用,可用于同步多個非同類事件。

Node.js中的示例用法:

// Read 3 files in parallel and process them together:function A (c){ fs.readFile('file1',c) };function B (c){ fs.readFile('file2',c) };function C (c){ fs.readFile('file3',c) };function D (result) {
  file1data = result[0][1];
  file2data = result[1][1];
  file3data = result[2][1];

  // process the files together here}fork([A,B,C],D);

更新

此代碼是在存在像async.js或各種基于promise的庫之類的庫之前編寫的。我想相信async.js的靈感來自于此,但我沒有任何證據。無論如何..如果你今天想要這樣做,請看看async.js或promises。只需考慮上面的答案,就async.parallel之類的工作方式做了很好的解釋/說明。

為了完整起見,以下是您如何做到這一點async.parallel

var async = require('async');async.parallel([A,B,C],D);

請注意,async.parallel它與fork我們上面實現的功能完全相同。主要區別在于它將第一個參數傳遞給錯誤,D并根據node.js約定將回調傳遞為第二個參數。

使用promises,我們將其編寫如下:

// Assuming A, B & C return a promise instead of accepting a callbackPromise.all([A,B,C]).then(D);


查看完整回答
1 反對 回復 2019-08-06
?
神不在的星期二

TA貢獻1963條經驗 獲得超6個贊

我相信現在“異步”模塊提供了這種并行功能,并且與上面的fork函數大致相同。


查看完整回答
反對 回復 2019-08-06
?
慕蓋茨4494581

TA貢獻1850條經驗 獲得超11個贊

期貨模塊有一個名為子模塊加入,我喜歡用:

將異步調用連接在一起類似于pthread_join線程的工作方式。

自述文件顯示了使用自由式或使用Promise模式使用未來子模塊的一些很好的例子。來自文檔的示例:

var Join = require('join')
  , join = Join()
  , callbackA = join.add()
  , callbackB = join.add()
  , callbackC = join.add();function abcComplete(aArgs, bArgs, cArgs) {
  console.log(aArgs[1] + bArgs[1] + cArgs[1]);}setTimeout(function () {
  callbackA(null, 'Hello');}, 300);setTimeout(function () {
  callbackB(null, 'World');}, 500);setTimeout(function () {
  callbackC(null, '!');}, 400);// this must be called after all join.when(abcComplete);


查看完整回答
反對 回復 2019-08-06
  • 3 回答
  • 0 關注
  • 860 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號