Promise.all

Promise.all 接收一个以 Promise 实例为成员的可迭代对象作为参数,当所有输入的 Promise 成员全部变为 Fulfilled 状态时才会继续执行后续的 Promise.prototype.then(),如果某个成员变为 Rejected 的时候,函数后续的 Promise.prototype.catch() 会被执行。

语法

语法:

Promise.all(values);

类型声明:

interface PromiseConstructor {
  all<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(
    values: readonly [
      T1 | PromiseLike<T1>,
      T2 | PromiseLike<T2>,
      T3 | PromiseLike<T3>,
      T4 | PromiseLike<T4>,
      T5 | PromiseLike<T5>,
      T6 | PromiseLike<T6>,
      T7 | PromiseLike<T7>,
      T8 | PromiseLike<T8>,
      T9 | PromiseLike<T9>,
      T10 | PromiseLike<T10>
    ]
  );

  all<T1, T2, T3, T4, T5, T6, T7, T8, T9>(
    values: readonly [
      T1 | PromiseLike<T1>,
      T2 | PromiseLike<T2>,
      T3 | PromiseLike<T3>,
      T4 | PromiseLike<T4>,
      T5 | PromiseLike<T5>,
      T6 | PromiseLike<T6>,
      T7 | PromiseLike<T7>,
      T8 | PromiseLike<T8>,
      T9 | PromiseLike<T9>
    ]
  );

  all<T1, T2, T3, T4, T5, T6, T7, T8>(
    values: readonly [
      T1 | PromiseLike<T1>,
      T2 | PromiseLike<T2>,
      T3 | PromiseLike<T3>,
      T4 | PromiseLike<T4>,
      T5 | PromiseLike<T5>,
      T6 | PromiseLike<T6>,
      T7 | PromiseLike<T7>,
      T8 | PromiseLike<T8>
    ]
  );

  all<T1, T2, T3, T4, T5, T6, T7>(
    values: readonly [
      T1 | PromiseLike<T1>,
      T2 | PromiseLike<T2>,
      T3 | PromiseLike<T3>,
      T4 | PromiseLike<T4>,
      T5 | PromiseLike<T5>,
      T6 | PromiseLike<T6>,
      T7 | PromiseLike<T7>
    ]
  );
  all<T1, T2, T3, T4, T5, T6>(
    values: readonly [
      T1 | PromiseLike<T1>,
      T2 | PromiseLike<T2>,
      T3 | PromiseLike<T3>,
      T4 | PromiseLike<T4>,
      T5 | PromiseLike<T5>,
      T6 | PromiseLike<T6>
    ]
  );
  all<T1, T2, T3, T4, T5>(
    values: readonly [
      T1 | PromiseLike<T1>,
      T2 | PromiseLike<T2>,
      T3 | PromiseLike<T3>,
      T4 | PromiseLike<T4>,
      T5 | PromiseLike<T5>
    ]
  );
  all<T1, T2, T3, T4>(
    values: readonly [
      T1 | PromiseLike<T1>,
      T2 | PromiseLike<T2>,
      T3 | PromiseLike<T3>,
      T4 | PromiseLike<T4>
    ]
  );
  all<T1, T2, T3>(
    values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>]
  );
  all<T1, T2>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]);
  all<T>(values: readonly [T | PromiseLike<T>]);
}

参数说明:

参数 参数说明 类型
values 见下方 any
  • 空的具备 Iterator 接口的对象,将返回 Fulfilled 状态的 Promise |
  • 不包含任何 Promise,将返回异步完成的 Promise |
  • 其他情况,将返回 Pending 状态的 Promise |
  • iterable:必须具备 Iterator 接口,且每个成员都是 Promise 实例。
  • 如果 iterable 内每个成员都不是 Promise 实例,会先调用 Promise.resolve 将每个成员转化为 Promise 实例,再进一步处理。

方法说明

Promise.all 执行后返回一个新创建的 Promise 实例,该实例状态由 Promise.all 参数成员决定,可以分为两种情况:

  • 当参数每个 Promise 实例成员均为 Resolved,返回值才会变为 Resolved 状态。此时参数每个 Promise 实例成员的返回值会组成一个数组,传递给回调函数。
  • 只要参数每个 Promise 实例成员之中有一个为 RejectedPromise.all 返回值就会变成 Rejected,此时第一个 Rejected 状态的 Promise 实例的返回值,会传递给回调函数。

⚠️ 注意:作为参数的 Promise 实例,自身定义的 catch 方法,那么它的状态一旦变更为 Rejected,并不会触发 Promise.allcatch 方法。

🌰 代码示例

const p1 = new Promise((resolve, reject) => {
  resolve('hello');
})
  .then((result) => result)
  .catch((err) => err);

const p2 = new Promise((resolve, reject) => {
  throw new Error('报错了');
})
  .then((result) => result)
  .catch((err) => err);

Promise.all([p1, p2])
  .then((result) => console.log(result)) // ["hello", Error: 报错了]
  .catch((err) => console.log(err));

代码示例

基本用法

Promise 等待所有 Promise 实例都 Fulfilled(或首个 Rejected)。

const p1 = Promise.resolve('3');
const p2 = 1234;
const p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([p1, p2, p3]).then((v) => console.log(v));
// ['3', 1234, 'foo']

快速返回否决行为

Promise.all 在任意一个传入的 Promise 否决时返回新的 Rejected 状态的 Promise 实例。

例如,如果你传入的 Promise 中,有四个 Promise 实例在一定的时间之后调用成功函数,有一个立即调用失败函数,那么 Promise.all 将立即变为 Rejected 状态。

var p1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 1000, 'one');
});

var p2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 2000, 'two');
});

var p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 3000, 'three');
});

var p4 = new Promise((resolve, reject) => {
  setTimeout(resolve, 4000, 'four');
});

var p5 = new Promise((resolve, reject) => {
  reject('reject');
});

// You can also use .catch
Promise.all([p1, p2, p3, p4, p5])
  .then((values) => {
    console.log(values);
  })
  .catch((reason) => {
    console.log(reason);
  });

完成时回调 Hack

如果你需要在所有的 Promise 都结束之后执行某些操作,而不论他们是否 Fulfilled,Promise.all 的这种机制就会成为一种限制,有个比较 Trick 的办法是给 .then.catch 传入相同的回调,显然,这会让代码的可读性大打折扣。

Promise.all(promises.map((p) => p.catch(() => undefined)));

如果 Promise 的 .catch 回调返回了 undefined,那么 Promise 的失败就会被当做成功来处理。

🌰 代码示例

Promise.all(
  [
    // Fulfilled
    Promise.resolve(1),
    // Rejects after 2 seconds
    new Promise((resolve, reject) => setTimeout(() => reject(1), 2000)),
  ].map((p) => p.catch(() => undefined))
).then(() => console.log('done!'));

// >> done!

参考资料