原文:
http://bluebirdjs.com/docs/api/promise.each.html
正文:
Promise.each
是一個非同步迭代函式,它接受一個可迭代物件(例如陣列)或一個可迭代物件的 Promise,並在每個元素上執行給定的迭代器函式。如果元素是一個 Promise,迭代器會等待它解決後再繼續。迭代器函式的簽名是(value, index, arrayLength),其中 value 是當前元素(如果它是一個 Promise,則為其解決後的值)。
如果在任何步驟中:
- 迭代器返回了一個 Promise 或一個 thenable,會等待它解決後再繼續下一個迭代。
- 當前迭代的元素是一個待解決的 Promise,會等待這個 Promise 解決後再執行迭代器。
- 當前迭代的元素是一個被拒絕的 Promise,迭代將停止,並且也會以同樣的原因被拒絕。
如果所有迭代都成功解決,Promise.each
呼叫將解決為一個新陣列,包含原始輸入元素的解決值。
Promise.each
與 Promise.mapSeries
非常相似。Promise.each
和 Promise.mapSeries
之間的差異在於它們的解決值。Promise.each
如上所述解決為一個陣列,而 Promise.mapSeries
解決為一個陣列,其中包含迭代器函式在每一步的輸出。這樣,Promise.each
主要用於副作用操作(因為迭代器的輸出基本上被丟棄了),就像陣列的原生 .forEach()
方法一樣,而 Promise.map
用作陣列的原生 .map()
方法的非同步版本。
基本示例:
// 要迭代的陣列可以是值和 Promise 的混合。
var fileNames = ["1.txt", Promise.resolve("2.txt"), "3.txt", Promise.delay(3000, "4.txt"), "5.txt"];
Promise.each(fileNames, function(fileName, index, arrayLength) {
// 迭代將順序執行,等待過程中的任何 Promise。
return fs.readFileAsync(fileName).then(function(fileContents) {
// ...
// 迭代器的最終解決值是不相關的,因為 `Promise.each` 的結果與迭代器的輸出無關。
return "anything"; // 不重要
});
}).then(function(result) {
// 這將在最後一步完成後執行
console.log("Done!");
console.log(result); // ["1.txt", "2.txt", "3.txt", "4.txt", "5.txt"]
});
包含陣列中被拒絕 Promise 的示例:
// 如果原始陣列中的一個 Promise 被拒絕,
// 一旦遇到它,迭代將停止
var items = ["A", Promise.delay(8000, "B"), Promise.reject("C"), "D"];
Promise.each(items, function(item) {
return Promise.delay(4000).then(function() {
console.log("On iterator: " + item);
});
}).then(function(result) {
// 這不會執行
}).catch(function(rejection) {
console.log("Catch: " + rejection);
});
// 上面的程式碼在 12 秒後輸出以下內容(不是 16 秒!):
// On iterator: A
// On iterator: B
// Catch: C
解釋:Promise.each
函式用於按順序處理陣列中的每個元素,如果元素是 Promise,則會等待它解決。如果迭代器函式返回一個 Promise,會等待它解決後再繼續。如果遇到被拒絕的 Promise,迭代將停止。如果所有迭代都成功,Promise.each
將解決為一個包含原始輸入元素解決值的陣列。這與 Promise.mapSeries
不同,後者會解決為一個包含迭代器函式輸出的陣列。