Start · Sprachen · JavaScript · Referenz · Promise.all()

Promise.all()

Methode

Die statische Methode <code>Promise.all()</code> nimmt ein iterable von Promises entgegen und liefert ein einzelnes Promise, das erfüllt wird, sobald alle Eingabe-Promises erfüllt sind.

Kategorie: method-property

Signatur

Promise.all(iterable)

Beschreibung

Die statische Methode Promise.all() nimmt ein iterable von Promises als Eingabe entgegen und gibt ein einzelnes Promise zurück. Dieses zurückgegebene Promise wird erfüllt, wenn alle Promises der Eingabe erfüllt werden (einschließlich, wenn ein leeres iterable übergeben wird), mit einem Array der Erfüllungswerte. Es wird abgelehnt (rejected), wenn eines der Eingabe-Promises abgelehnt wird, mit dem Grund dieser ersten Ablehnung.

Die Methode Promise.all() ist eine der Methoden zur Promise-Nebenläufigkeit (promise concurrency). Sie kann nützlich sein, um die Ergebnisse mehrerer Promises zusammenzufassen. Sie wird typischerweise verwendet, wenn es mehrere zusammenhängende asynchrone Aufgaben gibt, auf deren erfolgreiches Ausführen der Gesamtcode angewiesen ist — wobei wir alle erfüllen wollen, bevor die Code-Ausführung fortgesetzt wird.

Promise.all() wird sofort abgelehnt, sobald irgendein Eingabe-Promise abgelehnt wird. Im Vergleich dazu wartet das von Promise.allSettled() zurückgegebene Promise darauf, dass alle Eingabe-Promises abgeschlossen sind, unabhängig davon, ob eines abgelehnt wird oder nicht. Verwende allSettled(), wenn du das Endergebnis jedes Promise im Eingabe-iterable benötigst.

Wie andere Promise-Kombinatoren markiert Promise.all() alle Promises sofort als „handled", wenn es aufgerufen wird (indem ihre .then()-Methoden aufgerufen werden). Nachfolgende Ablehnungen nach der ersten Ablehnung werden ignoriert und lösen keine unhandledrejection-Events aus.

Die Ablehnung des zurückgegebenen Promise bricht die verbleibenden Operationen nicht ab und meldet die an ihre Promises angehängten Handler nicht ab. Das wiederholte Übergeben eines langlebigen ausstehenden Promise an Promise.all() kann Handler auf diesem Promise ansammeln, selbst wenn jedes Mal ein anderer Eingabewert abgelehnt wird.

Parameter

Name Typ Default Beschreibung
$iterable Pflicht Iterable Ein iterable (wie ein Array) von Promises. Diese Werte werden mit await abgewartet, sodass auch andere thenables aufgelöst werden, während Nicht-thenables unverändert zurückgegeben werden.

Rückgabewert

Typ
Promise
Beschreibung
Ein Promise, das ist: Bereits erfüllt, wenn das übergebene iterable leer ist. Asynchron erfüllt, 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 übergebene iterable nicht leer ist, aber keine ausstehenden Promises enthält, wird das zurückgegebene Promise dennoch asynchron (statt synchron) erfüllt. Asynchron abgelehnt, wenn eines der Promises im gegebenen iterable abgelehnt wird. Der Ablehnungsgrund ist der Ablehnungsgrund des ersten abgelehnten Promise.

Beispiele

Verwendung von Promise.all()

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"]
});

Nicht-Promise-Werte im iterable

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

Destrukturierung des Ergebnisses

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

// With await
const [a, b, c] = await Promise.all([p1, p2, p3]);

Asynchronität von Promise.all

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

Asynchrone Ablehnung

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 }

Synchrone Auflösung bei leerem iterable

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 mit async-Funktionen (schlecht)

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

Verwendung mit async-Funktionen (gut)

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

Fail-Fast-Verhalten von Promise.all

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"

Fail-Fast-Verhalten überschreiben

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"
  },
);