原文:
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()
方法的异步版本。
基本示例:
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
不同,后者会解决为一个包含迭代器函数输出的数组。