在本教程中,您将学习如何使用 Promise.all() 静态方法聚合来自多个异步操作的结果。

JavaScript Promise.all() 方法介绍

Promise.all() 静态方法接受一个可迭代Promise

Promise.all(iterable);

Promise.all() 方法返回一个 Promise,当输入的所有 Promise 都已解决时,此 Promise 将解决。返回结果将会包含输入的 Promise 结果数组:

在此图中,promise1 在 t1 时解析为值 v1,而 promise2 在 t2 时解析为值 v2。 因此,Promise.all(promise1, promise2) 返回一个 promise,此 promise 解析为包含 promise1 和 promise2 结果的数组 [v1, v2] 在 t2 时。

换句话说,Promise.all() 等待输入的所有 Promise 解析并返回一个 Promise,Promise 解析为包含输入 Promise 结果的数组。

如果其中一个输入 Promise 被拒绝,Promise.all() 方法会立即返回一个拒绝的Promise ,并返回第一个被拒绝 Promise 的错误:

在此图中,promise2 在 t1 时因错误而拒绝。 因此,Promise.all() 返回一个新的 promise,它会立即拒绝并返回相同的错误。 此外,Promise.all() 不关心其他输入的 Promise,无论它们将解决还是拒绝。

在实践中,Promise.all() 聚合多个异步操作的结果很有用。

JavaScript Promise.all() 方法示例

让我们举一些例子来理解这个 Promise.all() 方法是如何工作的。

已解决的 Promise

以下 Promise 在 1、2 和 3 秒后解析为 10、20 和 30。我们使用 setTimeout() 来模拟异步操作:

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('The first promise has resolved');
    resolve(10);
  }, 1 * 1000);
});
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('The second promise has resolved');
    resolve(20);
  }, 2 * 1000);
});
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('The third promise has resolved');
    resolve(30);
  }, 3 * 1000);
});

Promise.all([p1, p2, p3]).then((results) => {
  const total = results.reduce((p, c) => p + c);

  console.log(`Results: ${results}`);
  console.log(`Total: ${total}`);
});

输出

The first promise has resolved
The second promise has resolved
The third promise has resolved
Results: 10,20,30
Total: 60

当所有 Promise 都已解决时,这些 Promise 的值将作为数组传递到 then() 方法的回调。

在回调,我们使用 Array 的 reduce() 方法来计算总值并使用 console.log 来显示值数组和总计。

被拒绝的 Promise

如果任何输入 Promise 被拒绝,则 Promise.all() 返回一个被拒绝的 Promise。

const p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('The first promise has resolved');
        resolve(10);
    }, 1 * 1000);

});
const p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('The second promise has rejected');
        reject('Failed');
    }, 2 * 1000);
});
const p3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('The third promise has resolved');
        resolve(30);
    }, 3 * 1000);
});


Promise.all([p1, p2, p3])
    .then(console.log) // never execute
    .catch(console.log);

输出:

The first promise has resolved
The second promise has rejected
Failed
The third promise has resolved

在这个例子中,我们有三个 Promise :第一个在 1 秒后被解决,第二个在 2 秒后被拒绝,第三个在 3 秒后被解决。

结果,返回的 Promise 被拒绝,因为第二个 Promise 被拒绝。执行 catch() 方法以显示拒绝 Promise 的原因。

结论

  • Promise.all() 方法接受 Promise 列表并返回一个新的 Promise,如果所有输入 Promise 都已解决,则该 Promise 将解析为输入 Promise 的结果数组。如果输入的  Promise 其中一个被拒绝,Promise.all() 返回的 Promise 也会被拒绝。
  • 使用 Promise.all() 方法聚合来自多个异步操作的结果。