2013-06-01 55 views
2

我有一列我想要使用https://github.com/caolan/async並行運行的任務。如何在Node中完成第一個異步並行任務完成?

這些並行任務中的第一個完成後,我想讓程序繼續(可能是通過回調),而不是全部。所以我不認爲天真

async.parallel([task1, task2], callback) 

適合我。

或者我可以產生兩個任務,並取消不完整的,但我不知道如何使用異步做到這一點。

謝謝! -Charlie

+1

'異步'不能取消一個任務啓動它;之後,它只能等待它完成或忽略它。取消的能力必須與任務或擁有它的對象共存。類似於['XMLHttpRequest'的'.abort()'](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#abort())。 –

+0

這意味着我必須嘗試不同的方法 - 感謝您的信息! –

回答

6

並行賽

你可以得到async通過返回一個error,評估爲true但實際上不是一個錯誤發起最後的回調。

我把一個使用-1作爲錯誤代碼的例子放在一起。在最後的回調中,我檢查了error的值,如果它不是-1那麼這是一個實際的錯誤。如果錯誤值爲-1那麼我們將在results中有一個有效值。此時,我們只需要從results中刪除尚未完成的其他異步函數中的多餘元素。

在下面的示例中,我使用request模塊拉動html頁面,並使用underscore模塊過濾最終回調中的結果。

var request = require('request'); 
var _ = require('underscore'); 

exports.parallel = function(req, res) { 
    async.parallel([ 
    /* Grab Google.jp */ 
    function(callback) { 
     request("http://google.jp", function(err, response, body) { 
     if(err) { console.log(err); callback(true); return; } 
     callback(-1,"google.jp"); 
     }); 
    }, 
    /* Grab Google.com */ 
    function(callback) { 
     request("http://google.com", function(err, response, body) { 
     if(err) { console.log(err); callback(true); return; } 
     callback(-1,"google.com"); 
     }); 
    } 
    ], 
    /* callback handler */ 
    function(err, results) { 
     /* Actual error */ 
     if(err && err!=-1) { 
     console.log(err); 
     return; 
     } 
     /* First data */ 
     if(err===-1) { 
     /* 
     * async#parallel returns a list, one element per parallel function. 
     * Functions that haven't finished yet are in the list as undefined. 
     * use underscore to easily filter the one result. 
     */ 
     var one = _.filter(results, function(x) { 
      return (x===undefined ? false : true); 
     })[0]; 
     console.log(results); 
     console.log(one); 
     res.send(one); 
     } 
    } 
); 
}; 

剩餘函數結果

當你設置async#parallel到這樣的工作,你將不能訪問的其他異步函數的結果。如果你只對第一個迴應感興趣,那麼這不是問題。但是,您將無法取消其他請求。這很可能不是問題,但它可能是一個考慮因素。

+0

很好的解決方案,感謝代碼Daniel!不幸的是,我試圖運行的兩個任務很大,因此讓被忽略的任務完成時,計算起來非常昂貴。我可能會最終將任務分解成更小的塊,以便我可以節省浪費的週期,讓它完成忽略(如此設計)或者等待兩者完成。 –

1

async.parallel文件說:

如果有任何的功能傳遞一個錯誤的回調,主要的回調馬上打電話 與錯誤的值。

所以,你可以從所有您的並行仿函數返回一個錯誤的對象,並第一個完成會跳你到完成回調。也許甚至是你自己的特殊錯誤類,所以你可以分辨出真正的錯誤和「我贏了」錯誤。儘管如此,你仍然會運行你的並行函數,可能會等待回調完成或者其他任何事情。也許你可以使用async.parallelLimit來確保你沒有並行執行太多任務。

說了這麼多之後,最好通過從異步庫中嘗試另一種方法來完成此任務 - 解僱並行任務,然後讓這些任務相互競爭可能不是最好的主意。