Promise.each()

年华似水゛發表於2024-10-18

原文:

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.eachPromise.mapSeries 非常相似。Promise.eachPromise.mapSeries 之間的差異在於它們的解決值。Promise.each 如上所述解決為一個陣列,而 Promise.mapSeries 解決為一個陣列,其中包含迭代器函式在每一步的輸出。這樣,Promise.each 主要用於副作用操作(因為迭代器的輸出基本上被丟棄了),就像陣列的原生 .forEach() 方法一樣,而 Promise.map 用作陣列的原生 .map() 方法的非同步版本。

基本示例:

javascript
// 要迭代的陣列可以是值和 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 的示例:

javascript
// 如果原始陣列中的一個 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 不同,後者會解決為一個包含迭代器函式輸出的陣列。