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 einzelnes Promise zurück. Dieses zurückgegebene Promise wird erfüllt, wenn alle Promises der Eingabe erfüllt sind (einschließlich des Falls, wenn eine leere Iterable übergeben wird), mit einem Array der Erfüllungswerte. Es wird abgelehnt, wenn eines der Promises der Eingabe abgelehnt wird, und zwar mit dem Grund der ersten Ablehnung.

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

js
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 in dem übergebenen iterable erfüllt sind. Der Erfüllungswert ist ein Array von Erfüllungswerten in der Reihenfolge der übergebenen Promises, unabhängig von der Reihenfolge ihrer Fertigstellung. Wenn das übergebene iterable nicht leer ist, aber keine ausstehenden Promises enthält, wird das zurückgegebene Promise dennoch asynchron (anstatt synchron) erfüllt.
  • Asynchron abgelehnt wird, wenn eines der Promises in dem übergebenen iterable abgelehnt wird. Der Ablehnungsgrund ist der Ablehnungsgrund des ersten abgelehnten Promises.

Beschreibung

Die Methode Promise.all() ist eine der Konkurrenzmethoden von Promises. Sie ist nützlich, um die Ergebnisse mehrerer Promises zu aggregieren. Sie wird typischerweise verwendet, wenn es mehrere verwandte asynchrone Aufgaben gibt, die der gesamte Code für eine erfolgreiche Ausführung benötigt — und wir möchten, dass alle erfüllt sind, bevor die Ausführung des Codes fortgesetzt wird.

Promise.all() wird sofort abgelehnt, wenn ein einziges Promise der Eingabe abgelehnt wird. Im Vergleich dazu wartet das Promise, das von Promise.allSettled() zurückgegeben wird, darauf, dass alle Eingabepromises abgeschlossen sind, unabhängig davon, ob eines abgelehnt wird oder nicht. Verwenden Sie allSettled(), wenn Sie das Endergebnis jedes Promises im Eingabe-iterierbaren Objekt benötigen.

Beispiele

Verwendung von Promise.all()

Promise.all wartet auf alle Erfüllungen (oder die erste Ablehnung).

js
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 Nicht-Promise-Werte enthält, werden diese ignoriert, aber dennoch in der Array-Ausgabe des erfüllten Promises gezählt:

js
// 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 }

Asynchrone oder synchrone Natur von Promise.all

Das folgende Beispiel zeigt die Asynchronität von Promise.all, wenn ein nicht-leeres iterable übergeben wird:

js
// 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] }

Das Gleiche passiert, wenn Promise.all abgelehnt wird:

js
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 wird synchron erfüllt, wenn und nur wenn das übergebene iterable leer ist:

js
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 üblich, dass der Code "übermäßig aufgerufen" wird. Zum Beispiel, bei den folgenden Funktionen:

js
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();
}

Sie könnten eine Funktion wie diese schreiben:

js
async function getPrice() {
  const choice = await promptForDishChoice();
  const prices = await fetchPrices();
  return prices[choice];
}

Es ist jedoch zu beachten, dass die Ausführung von promptForDishChoice und fetchPrices nicht von den Ergebnissen des jeweils anderen abhängt. Während der Benutzer seine Wahl trifft, ist es völlig in Ordnung, wenn die Preise im Hintergrund abgerufen werden, aber im obigen Code sorgt der await-Operator dafür, dass die asynchrone Funktion pausiert, bis die Wahl getroffen ist, und danach erneut bis die Preise abgerufen sind. Wir können Promise.all verwenden, um sie gleichzeitig auszuführen, damit der Benutzer nicht darauf warten muss, dass die Preise abgerufen werden, bevor ein Ergebnis angezeigt wird:

js
async function getPrice() {
  const [choice, prices] = await Promise.all([
    promptForDishChoice(),
    fetchPrices(),
  ]);
  return prices[choice];
}

Promise.all ist hier die beste Wahl unter den Konkurrenzmethoden, da das Fehlerhandling intuitiv ist — wenn eines der Promises abgelehnt wird, ist das Ergebnis nicht mehr verfügbar, und der gesamte await-Ausdruck wirft eine Ausnahme.

Promise.all akzeptiert ein iterierbares Objekt von Promises. Wenn Sie es verwenden, um mehrere asynchrone Funktionen gleichzeitig auszuführen, müssen Sie die asynchronen Funktionen aufrufen und die zurückgegebenen Promises übergeben. Ein direktes Übergeben der Funktionen an Promise.all funktioniert nicht, da diese keine Promises sind.

js
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 "Fail-fast"-Verhalten von Promise.all

Promise.all wird abgelehnt, wenn eines der Elemente abgelehnt wird. Zum Beispiel, wenn Sie vier Promises übergeben, die nach einer Verzögerung aufgelöst werden, und eines, das sofort abgelehnt wird, wird Promise.all sofort abgelehnt.

js
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 potenzielle Ablehnungen behandelt werden:

js
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® 2025 Language Specification
# sec-promise.all

Browser-Kompatibilität

BCD tables only load in the browser

Siehe auch