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];
}
但是,请注意,promptForDishChoice
和 fetchPrices
的执行彼此之间没有依赖关系。当用户选择菜肴时,可以在后台获取价格,但在上面的代码中,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