異步編程比同步編程困難得多。NodeJS:for循環和承諾
使用的NodeJS,我想以下幾點:
for (var i = 0; i < 10; i++) {
someFunction().then(function() {
// Do stuff
});
}
但我希望在做的東西的一部分已經完成了迴路只能繼續。
任何想法如何輕易實現...?
謝謝!
異步編程比同步編程困難得多。NodeJS:for循環和承諾
使用的NodeJS,我想以下幾點:
for (var i = 0; i < 10; i++) {
someFunction().then(function() {
// Do stuff
});
}
但我希望在做的東西的一部分已經完成了迴路只能繼續。
任何想法如何輕易實現...?
謝謝!
異步編程可能會造成混淆,但大多數的混亂是可以消除,如果你記住的東西保持像回調和then
將在稍後的時間運行,代碼後它們包含的塊已經完成。
Promise庫,async
模塊,都試圖獲得更多的控制程序的流量。這裏有一個解釋不同方法的解決方案,通過查看針對同一問題的不同解決方案,幫助我理解事物。
其他一些答案提到Q.all()
。如果你已經有了一系列的承諾,這個效果很好。
如果您有一組值或承諾,還有另一個庫使得這更容易,名爲bluebird
。它有一個名爲.map()
的方法,您可以使用該方法與數組一起啓動承諾鏈。
使用這種方法,您不需要調用異步,promise返回函數,將返回的promise保存在數組中,然後將該數組傳遞給Q.all
。它爲您節省了一些步驟。
因此,假設您擁有的只是一個數組值:
var items = [0,1,2,3,4,5,6,7,8,9];
你可以做類似如下:
Promise.map(items, function (item) {
return performAsyncOperation(item);
}, {concurrency: n})
.then(function(allResults){
// 'allResults' now contains an array of all
// the results of 'performAsyncOperation'
})
注意:對於這個達到預期效果, performAsyncOperation
必須返回承諾
還請注意Promise.map()
的第三個參數:{concurrency: n}
。如果指定了這個選項,bluebird將只允許一次執行n
操作,如果您有大量要處理的項目會對系統造成壓倒,如果它們全部被啓動(網絡連接,文件句柄等)。
最後說明:這裏是bluebird API doc。這本書寫得非常好,有很多例子,也是探索承諾如何幫助您輕鬆生活的絕佳方式。
希望它有幫助!
使用Q.all等待所有承諾繼續
要擴大Anders的答案之前解決,這是怎麼了,我的過去的情況需要被期待已久的多個承諾處理這樣的:
var promises = [];
for (var i = 0; i < 10; i++) {
promises.push(someFunction().then(function() {
// Do stuff
})
);
}
Q.all(promises)
.then(function() {
// Do all the things!
})
你可以鏈你的承諾與reduce
:
array.reduce(function(promise, elt) {
return promise.then(function() { return long_process(elt); });
}, new Promise.resolve());
這個表達式的結果將是操作的順序已經完成的承諾。這些代碼不是隻調用十個異步操作並等待它們全部完成,而是等到第一個操作完成後再啓動第二個操作,如果這很重要的話。
我喜歡在這種情況下使用的模式是定義一個函數,在異步操作完成後調用它自己。你的例子是在該行:
var times = 10;
var current = 0;
(function nextLap() {
if (current >= times) {
return callback();
}
++current;
someFunction()
.then(function() {
// do stuff
nextLap();
})
.catch(callback);
})();
看來,OP可能希望執行承諾的啓動順序,換句話說,只有當第一個完成時才啓動第二個進程。 – 2014-10-10 11:36:06