# 1. 前言
详细见:Promise.all() (opens new window)
# 1. Promise.all
# 1.1 描述
Promise.all()方法接收一个promise的iterable类型(注:Array,Map,Set都属于 ES6 的 iterable类型)的输入,并且只返回一个Promise实例, 那个输入的所有 promise的 resolve回调的结果是一个数组。
# 1.2 语法
Promise.all(iterable);
# 1.3 参数
- iterable:一个可迭代对象,如 Array 或 String。
# 1.4 返回值
如果传入的参数是一个空的可迭代对象,则返回一个已完成(already resolved)状态的 Promise。
如果传入的参数不包含任何 promise,则返回一个异步完成(asynchronously resolved) Promise。注意:Google Chrome 58 在这种情况下返回一个已完成(already resolved)状态的 Promise。
其它情况下返回一个处理中(pending)的 Promise。这个返回的 promise 之后会在所有的 promise 都完成或有一个 promise 失败时异步地变为完成或失败。 见下方关于“Promise.all 的异步或同步”示例。返回值将会按照参数内的 promise 顺序排列,而不是由调用 promise 的完成顺序决定。
# 1.5 说明
此方法在集合多个 promise 的返回结果时很有用。
**完成(Fulfillment):**如果传入的可迭代对象为空,Promise.all 会同步地返回一个已完成(resolved)状态的 promise。 如果所有传入的 promise 都变为完成状态,或者传入的可迭代对象内没有 promise,Promise.all 返回的 promise 异步地变为完成。
在任何情况下,Promise.all 返回的 promise 的完成状态的结果都是一个数组,它包含所有的传入迭代参数对象的值(也包括非 promise 值)。
**失败/拒绝(Rejection):**如果传入的 promise 中有一个失败(rejected),Promise.all 异步地将失败的那个结果给失败状态的回调函数,而不管其它 promise 是否完成。
# 1.6 实现
function PromiseAll(promises = []) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
reject("PromiseAll 参数必须为数组");
}
let resloveNum = 0; //记录reslove的个数
const promisesLength = promises.length;
const result = [];
promises.forEach((item, index) => {
let actionItem = item;
// 如果不是promise实例,使用Promise.resolve转换成 Promise 实例
if (!(item instanceof Promise)) {
actionItem = Promise.resolve(item);
}
actionItem
.then((res) => {
resloveNum++;
result[index] = res; //确保返回顺序和参数顺序一致
if (resloveNum === promisesLength) {
resolve(result);
}
})
.catch((res) => {
reject(res);
});
});
});
}
// 测试
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1);
}, 1000);
});
const p2 = 2;
const p3 = Promise.resolve(3);
const p4 = Promise.reject(4);
PromiseAll([p1, p2, p3])
.then((res) => {
console.log("resolve", res);
})
.catch((res) => {
console.log("catch", res);
});
// 1秒后输出 resolve [1,2,3]
PromiseAll([p2, p3, p4])
.then((res) => {
console.log("resolve", res);
})
.catch((res) => {
console.log("catch", res);
});
// 输出 catch 4
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54