Promise.all()

基线 广泛可用

此功能已得到很好的建立,并且适用于许多设备和浏览器版本。它自 2015 年 7 月.

报告反馈

试一试

语法

**Promise.all()** 静态方法将可迭代的 Promise 作为输入,并返回单个 Promise。此返回的 Promise 在所有输入的 Promise 都完成时完成(包括传递空可迭代对象时),并包含一个包含完成值的数组。当任何输入的 Promise 拒绝时,它会拒绝,并包含第一个拒绝原因。
Promise.all(iterable)

js

参数

可迭代对象

一个 可迭代对象(例如 Array)的 Promise。

返回值

  • 一个 Promise,它
  • **已完成**,如果传递的 iterable 为空。
  • **异步完成**,当给定 iterable 中的所有 Promise 都完成时。完成值是一个包含完成值的数组,以传递的 Promise 的顺序排列,与完成顺序无关。如果传递的 iterable 不为空,但没有包含任何待处理的 Promise,则返回的 Promise 仍然是异步(而不是同步)完成的。

描述

**异步拒绝**,当给定 iterable 中的任何 Promise 拒绝时。拒绝原因是第一个被拒绝的 Promise 的拒绝原因。

Promise.all() 方法是 Promise 并发 方法之一。它对于聚合多个 Promise 的结果非常有用。它通常用于多个相关的异步任务,这些任务是代码成功执行所依赖的 — 我们希望在代码执行继续之前完成所有这些任务。

示例

Promise.all() 将在**任何**输入的 Promise 拒绝时立即拒绝。相比之下,由 Promise.allSettled() 返回的 Promise 将等待所有输入的 Promise 完成,无论它们是否拒绝。如果您需要输入可迭代对象中每个 Promise 的最终结果,请使用 allSettled()

使用 Promise.all()

**Promise.all()** 静态方法将可迭代的 Promise 作为输入,并返回单个 Promise。此返回的 Promise 在所有输入的 Promise 都完成时完成(包括传递空可迭代对象时),并包含一个包含完成值的数组。当任何输入的 Promise 拒绝时,它会拒绝,并包含第一个拒绝原因。
const p1 = Promise.resolve(3);
const p2 = 1337;
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("foo");
  }, 100);
});

Promise.all([p1, p2, p3]).then((values) => {
  console.log(values); // [3, 1337, "foo"]
});

Promise.all 等待所有完成(或第一个拒绝)。

**Promise.all()** 静态方法将可迭代的 Promise 作为输入,并返回单个 Promise。此返回的 Promise 在所有输入的 Promise 都完成时完成(包括传递空可迭代对象时),并包含一个包含完成值的数组。当任何输入的 Promise 拒绝时,它会拒绝,并包含第一个拒绝原因。
// All values are non-promises, so the returned promise gets fulfilled
const p = Promise.all([1, 2, 3]);
// The only input promise is already fulfilled,
// so the returned promise gets fulfilled
const p2 = Promise.all([1, 2, 3, Promise.resolve(444)]);
// One (and the only) input promise is rejected,
// so the returned promise gets rejected
const p3 = Promise.all([1, 2, 3, Promise.reject(555)]);

// Using setTimeout, we can execute code after the queue is empty
setTimeout(() => {
  console.log(p);
  console.log(p2);
  console.log(p3);
});

// Logs:
// Promise { <state>: "fulfilled", <value>: Array[3] }
// Promise { <state>: "fulfilled", <value>: Array[4] }
// Promise { <state>: "rejected", <reason>: 555 }

如果 iterable 包含非 Promise 值,它们将被忽略,但在返回的 Promise 数组值中仍然会被计入(如果 Promise 已完成)。

Promise.all 的异步性或同步性

**Promise.all()** 静态方法将可迭代的 Promise 作为输入,并返回单个 Promise。此返回的 Promise 在所有输入的 Promise 都完成时完成(包括传递空可迭代对象时),并包含一个包含完成值的数组。当任何输入的 Promise 拒绝时,它会拒绝,并包含第一个拒绝原因。
// Passing an array of promises that are already resolved,
// to trigger Promise.all as soon as possible
const resolvedPromisesArray = [Promise.resolve(33), Promise.resolve(44)];

const p = Promise.all(resolvedPromisesArray);
// Immediately logging the value of p
console.log(p);

// Using setTimeout, we can execute code after the queue is empty
setTimeout(() => {
  console.log("the queue is now empty");
  console.log(p);
});

// Logs, in order:
// Promise { <state>: "pending" }
// the queue is now empty
// Promise { <state>: "fulfilled", <value>: Array[2] }

以下示例演示了当传递非空 iterable 时,Promise.all 的异步性。

**Promise.all()** 静态方法将可迭代的 Promise 作为输入,并返回单个 Promise。此返回的 Promise 在所有输入的 Promise 都完成时完成(包括传递空可迭代对象时),并包含一个包含完成值的数组。当任何输入的 Promise 拒绝时,它会拒绝,并包含第一个拒绝原因。
const mixedPromisesArray = [Promise.resolve(33), Promise.reject(44)];
const p = Promise.all(mixedPromisesArray);
console.log(p);
setTimeout(() => {
  console.log("the queue is now empty");
  console.log(p);
});

// Logs:
// Promise { <state>: "pending" }
// the queue is now empty
// Promise { <state>: "rejected", <reason>: 44 }

如果 Promise.all 拒绝,也会发生同样的事情。

**Promise.all()** 静态方法将可迭代的 Promise 作为输入,并返回单个 Promise。此返回的 Promise 在所有输入的 Promise 都完成时完成(包括传递空可迭代对象时),并包含一个包含完成值的数组。当任何输入的 Promise 拒绝时,它会拒绝,并包含第一个拒绝原因。
const p = Promise.all([]); // Will be immediately resolved
const p2 = Promise.all([1337, "hi"]); // Non-promise values are ignored, but the evaluation is done asynchronously
console.log(p);
console.log(p2);
setTimeout(() => {
  console.log("the queue is now empty");
  console.log(p2);
});

// Logs:
// Promise { <state>: "fulfilled", <value>: Array[0] }
// Promise { <state>: "pending" }
// the queue is now empty
// Promise { <state>: "fulfilled", <value>: Array[2] }

Promise.all 仅在传递的 iterable 为空时才同步解析。

将 Promise.all() 与异步函数一起使用

**Promise.all()** 静态方法将可迭代的 Promise 作为输入,并返回单个 Promise。此返回的 Promise 在所有输入的 Promise 都完成时完成(包括传递空可迭代对象时),并包含一个包含完成值的数组。当任何输入的 Promise 拒绝时,它会拒绝,并包含第一个拒绝原因。
function promptForDishChoice() {
  return new Promise((resolve, reject) => {
    const dialog = document.createElement("dialog");
    dialog.innerHTML = `
<form method="dialog">
  <p>What would you like to eat?</p>
  <select>
    <option value="pizza">Pizza</option>
    <option value="pasta">Pasta</option>
    <option value="salad">Salad</option>
  </select>
  <menu>
    <li><button value="cancel">Cancel</button></li>
    <li><button type="submit" value="ok">OK</button></li>
  </menu>
</form>
    `;
    dialog.addEventListener("close", () => {
      if (dialog.returnValue === "ok") {
        resolve(dialog.querySelector("select").value);
      } else {
        reject(new Error("User cancelled dialog"));
      }
    });
    document.body.appendChild(dialog);
    dialog.showModal();
  });
}

async function fetchPrices() {
  const response = await fetch("/prices");
  return await response.json();
}

异步函数 中,通常会“过度等待”代码。例如,给定以下函数

**Promise.all()** 静态方法将可迭代的 Promise 作为输入,并返回单个 Promise。此返回的 Promise 在所有输入的 Promise 都完成时完成(包括传递空可迭代对象时),并包含一个包含完成值的数组。当任何输入的 Promise 拒绝时,它会拒绝,并包含第一个拒绝原因。
async function getPrice() {
  const choice = await promptForDishChoice();
  const prices = await fetchPrices();
  return prices[choice];
}

您可以这样编写函数

**Promise.all()** 静态方法将可迭代的 Promise 作为输入,并返回单个 Promise。此返回的 Promise 在所有输入的 Promise 都完成时完成(包括传递空可迭代对象时),并包含一个包含完成值的数组。当任何输入的 Promise 拒绝时,它会拒绝,并包含第一个拒绝原因。
async function getPrice() {
  const [choice, prices] = await Promise.all([
    promptForDishChoice(),
    fetchPrices(),
  ]);
  return prices[choice];
}

但是,请注意,promptForDishChoicefetchPrices 的执行彼此之间没有依赖关系。当用户选择菜肴时,可以在后台获取价格,但在上面的代码中,await 运算符会导致异步函数暂停,直到选择完成,然后再次暂停,直到获取价格。我们可以使用 Promise.all 并发地运行它们,这样用户就不必等待获取价格,才能获得结果。

Promise.all并发方法 的最佳选择,因为错误处理很直观 — 如果任何 Promise 拒绝,结果将不再可用,因此整个 await 表达式都会抛出异常。

**Promise.all()** 静态方法将可迭代的 Promise 作为输入,并返回单个 Promise。此返回的 Promise 在所有输入的 Promise 都完成时完成(包括传递空可迭代对象时),并包含一个包含完成值的数组。当任何输入的 Promise 拒绝时,它会拒绝,并包含第一个拒绝原因。
async function getPrice() {
  const [choice, prices] = await Promise.all([
    promptForDishChoice,
    fetchPrices,
  ]);
  // `choice` and `prices` are still the original async functions;
  // Promise.all() does nothing to non-promises
}

Promise.all 接受可迭代的 Promise,因此如果您使用它来并发地运行多个异步函数,您需要调用异步函数并使用返回的 Promise。直接将函数传递给 Promise.all 不起作用,因为它们不是 Promise。

Promise.all 快速失败行为

**Promise.all()** 静态方法将可迭代的 Promise 作为输入,并返回单个 Promise。此返回的 Promise 在所有输入的 Promise 都完成时完成(包括传递空可迭代对象时),并包含一个包含完成值的数组。当任何输入的 Promise 拒绝时,它会拒绝,并包含第一个拒绝原因。
const p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("one"), 1000);
});
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("two"), 2000);
});
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("three"), 3000);
});
const p4 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("four"), 4000);
});
const p5 = new Promise((resolve, reject) => {
  reject(new Error("reject"));
});

// Using .catch:
Promise.all([p1, p2, p3, p4, p5])
  .then((values) => {
    console.log(values);
  })
  .catch((error) => {
    console.error(error.message);
  });

// Logs:
// "reject"

如果任何元素拒绝,则 Promise.all 会被拒绝。例如,如果您传入四个在超时后解析的 Promise 和一个立即拒绝的 Promise,那么 Promise.all 将立即拒绝。

**Promise.all()** 静态方法将可迭代的 Promise 作为输入,并返回单个 Promise。此返回的 Promise 在所有输入的 Promise 都完成时完成(包括传递空可迭代对象时),并包含一个包含完成值的数组。当任何输入的 Promise 拒绝时,它会拒绝,并包含第一个拒绝原因。
const p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p1_delayed_resolution"), 1000);
});

const p2 = new Promise((resolve, reject) => {
  reject(new Error("p2_immediate_rejection"));
});

Promise.all([p1.catch((error) => error), p2.catch((error) => error)]).then(
  (values) => {
    console.log(values[0]); // "p1_delayed_resolution"
    console.error(values[1]); // "Error: p2_immediate_rejection"
  },
);

规范

可以通过处理可能的拒绝来更改此行为。
规范
# ECMAScript 语言规范

浏览器兼容性

sec-promise.all

另请参阅