Promise.all()
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
Die statische Methode Promise.all()
nimmt ein iterierbares Objekt von Promises als Eingabe und gibt ein einziges Promise
zurück. Diese zurückgegebene Promise wird erfüllt, wenn alle Promises der Eingabe erfüllt werden (einschließlich wenn ein leeres iterierbares Objekt übergeben wird), und zwar mit einem Array der Erfüllungswerte. Sie wird abgelehnt, wenn eine der Promises der Eingabe abgelehnt wird, mit diesem ersten Ablehnungsgrund.
Probieren Sie es aus
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "foo");
});
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values);
});
// Expected output: Array [3, 42, "foo"]
Syntax
Promise.all(iterable)
Parameter
iterable
-
Ein iterierbares Objekt (wie ein
Array
) von Promises.
Rückgabewert
Ein Promise
, das:
- Bereits erfüllt ist, wenn das übergebene
iterable
leer ist. - Asynchron erfüllt wird, wenn alle Promises im gegebenen
iterable
erfüllt werden. Der Erfüllungswert ist ein Array der Erfüllungswerte, in der Reihenfolge der übergebenen Promises, unabhängig von der Reihenfolge der Fertigstellung. Wenn das übergebeneiterable
nicht leer ist, aber keine ausstehenden Promises enthält, wird die zurückgegebene Promise trotzdem asynchron (statt synchron) erfüllt. - Asynchron abgelehnt wird, wenn eine der Promises im gegebenen
iterable
abgelehnt wird. Der Ablehnungsgrund ist der Ablehnungsgrund der ersten Promise, die abgelehnt wurde.
Beschreibung
Die Methode Promise.all()
ist eine der Methoden für Promise-Konkurrenz. Sie kann nützlich sein, um die Ergebnisse mehrerer Promises zu aggregieren. Sie wird typischerweise verwendet, wenn es mehrere verwandte asynchrone Aufgaben gibt, auf die der gesamte Code angewiesen ist, um erfolgreich zu arbeiten - alle von ihnen sollen erfüllt werden, bevor die Codeausführung fortgesetzt wird.
Promise.all()
wird sofort abgelehnt, sobald eine der Eingabe-Promises abgelehnt wird. Im Vergleich dazu wird die Promise, die von Promise.allSettled()
zurückgegeben wird, auf alle Eingabe-Promises warten, um zu beenden, unabhängig davon, ob eines abgelehnt wird oder nicht. Verwenden Sie allSettled()
, wenn Sie das Endergebnis jeder Promise im Eingabeiterable benötigen.
Beispiele
Verwendung von Promise.all()
Promise.all
wartet auf alle Erfüllungen (oder die erste Ablehnung).
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"]
});
Wenn das iterable
Werte enthält, die keine Promises sind, werden diese ignoriert, aber immer noch im zurückgegebenen Promise-Array-Wert gezählt (wenn die Promise erfüllt wird):
// 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(new Error("bad"))]);
// 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>: Error: bad }
Asynchronität oder Synchronität von Promise.all
Das folgende Beispiel demonstriert die Asynchronität von Promise.all
, wenn ein nicht leeres iterable
übergeben wird:
// 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] }
Dasselbe passiert, wenn Promise.all
abgelehnt wird:
const mixedPromisesArray = [
Promise.resolve(33),
Promise.reject(new Error("bad")),
];
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>: Error: bad }
Promise.all
wird nur synchron aufgelöst, wenn das übergebene iterable
leer ist:
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] }
Verwendung von Promise.all() mit asynchronen Funktionen
Innerhalb von asynchronen Funktionen ist es sehr häufig, dass Ihr Code "über-wartet". Zum Beispiel mit den folgenden Funktionen:
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();
}
Könnten Sie eine Funktion wie diese schreiben:
async function getPrice() {
const choice = await promptForDishChoice();
const prices = await fetchPrices();
return prices[choice];
}
Beachten Sie jedoch, dass die Ausführung von promptForDishChoice
und fetchPrices
nicht von den Ergebnissen des jeweils anderen abhängt. Während der Benutzer ihre Speise auswählt, ist es unproblematisch, wenn die Preise im Hintergrund abgerufen werden, aber im obigen Code verursacht der await
-Operator, dass die asynchrone Funktion pausiert, bis die Auswahl getroffen wurde und dann erneut, bis die Preise abgerufen sind. Wir können Promise.all
verwenden, um sie gleichzeitig auszuführen, damit der Benutzer nicht warten muss, bis die Preise abgerufen werden, bevor das Ergebnis angezeigt wird:
async function getPrice() {
const [choice, prices] = await Promise.all([
promptForDishChoice(),
fetchPrices(),
]);
return prices[choice];
}
Promise.all
ist die beste Wahl der Konkurrenzmethoden hier, weil die Fehlerbehandlung intuitiv ist — wenn einer der Promises abgelehnt wird, ist das Ergebnis nicht mehr verfügbar, sodass der gesamte await
-Ausdruck eine Ausnahme wirft.
Promise.all
akzeptiert ein iterierbares Objekt von Promises, sodass Sie, wenn Sie es verwenden, um mehrere asynchrone Funktionen gleichzeitig auszuführen, die asynchronen Funktionen aufrufen und die zurückgegebenen Promises verwenden müssen. Das direkte Übergeben der Funktionen an Promise.all
funktioniert nicht, da sie keine Promises sind.
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
}
Das schnelle Abbruchverhalten von Promise.all
Promise.all
wird abgelehnt, wenn eines der Elemente abgelehnt wird. Wenn Sie zum Beispiel vier Promises übergeben, die nach einer Verzögerung aufgelöst werden, und eine Promise, die sofort abgelehnt wird, wird Promise.all
sofort abgelehnt.
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"
Es ist möglich, dieses Verhalten zu ändern, indem mögliche Ablehnungen behandelt werden:
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"
},
);
Spezifikationen
Specification |
---|
ECMAScript® 2026 Language Specification # sec-promise.all |