# 1. 前言

详细见:Promise.all() (opens new window)

# 1. Promise.all

# 1.1 描述

Promise.all()方法接收一个promiseiterable类型(注:ArrayMapSet都属于 ES6 的 iterable类型)的输入,并且只返回一个Promise实例, 那个输入的所有 promiseresolve回调的结果是一个数组。

# 1.2 语法

Promise.all(iterable);
1

# 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
1
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