JavaScript Promise API
Die JavaScript Promise API: Promise.all, allSettled, race, any sowie resolve und reject. Fast-fail vs. allSettled mit ausführbaren Beispielen und einer Übersichtstabelle.
Die Klasse Promise bietet mehrere statische Methoden zum Kombinieren und Erstellen von Promises. Anstatt mehrere .then()-Ketten manuell zu verknüpfen, übergibt man ein array von Promises an einen Kombinator und erhält ein einzelnes Promise zurück, das sich auflöst, sobald die Gruppe einen definierten Zustand erreicht.
Diese Seite behandelt die vier Kombinatoren — Promise.all, Promise.allSettled, Promise.race und Promise.any — sowie die zwei Erstellungs-Hilfsmethoden Promise.resolve und Promise.reject. Wenn Sie neu bei Promises sind, beginnen Sie zunächst mit JavaScript: Promises.
Die folgenden Beispiele verwenden
.then()/.catch(), damit der Kontrollfluss explizit ist. Im echten Code würde man das Ergebnis üblicherweise mitasync/awaitlesen.
Den richtigen Kombinator wählen
| Methode | Löst auf, wenn… | Lehnt ab, wenn… | Typischer Einsatz |
|---|---|---|---|
Promise.all | alle Promises erfüllt werden | irgendeins abgelehnt wird (fast-fail) | Wenn alle Ergebnisse benötigt werden und ein Fehler die ganze Gruppe abbrechen soll |
Promise.allSettled | alle Promises abgeschlossen sind (lehnt nie ab) | — | Wenn jedes Ergebnis gewünscht wird, ob Erfolg oder Fehler |
Promise.race | das erste Promise abgeschlossen ist (erfüllt oder abgelehnt) | das erste Promise zuerst abgelehnt wird | Timeouts, „Erster antwortet gewinnt" |
Promise.any | das erste Promise erfüllt wird | alle Promises abgelehnt werden | Erstes erfolgreiches Ergebnis, einzelne Fehler ignorieren |
Der entscheidende Unterschied: Promise.all schlägt sofort fehl — es wird in dem Moment abgelehnt, in dem ein Eingabe-Promise abgelehnt wird, auch wenn andere Promises noch ausstehen. Wenn stattdessen auf jedes Promise gewartet werden soll, egal was passiert, sollte Promise.allSettled verwendet werden.
Promise.all für gleichzeitige Aufgaben nutzen
Promise.all ist eine wesentliche Methode zur gleichzeitigen Verarbeitung mehrerer Promises. Wenn mehrere asynchrone Operationen ausgeführt werden müssen und erst fortgefahren werden soll, wenn alle erfolgreich abgeschlossen sind, ist Promise.all das richtige Werkzeug.
Promise.all implementieren
Nachfolgend ein Beispiel, das zeigt, wie Promise.all für die gleichzeitige Verarbeitung mehrerer API-Anfragen verwendet wird:
In diesem Beispiel nimmt Promise.all ein array von Promises entgegen und löst sich in ein array ihrer Ergebnisse auf — in der gleichen Reihenfolge wie die Eingabe (nicht in der Reihenfolge, in der sie abgeschlossen wurden). Wenn ein Promise abgelehnt wird, lehnt Promise.all sofort mit dem Grund dieser ersten Ablehnung ab — die Ergebnisse der anderen werden verworfen. Unter Fehlerbehandlung mit Promises erfahren Sie, wie man sich von solchen Fehlern erholt.
Promise.allSettled meistern
Im Gegensatz zu Promise.all gibt die Methode Promise.allSettled ein Promise zurück, das sich auflöst, nachdem alle übergebenen Promises entweder aufgelöst oder abgelehnt wurden — mit einem array von Objekten, die jeweils das Ergebnis jedes einzelnen Promises beschreiben.
Beispiel für Promise.allSettled
So lässt sich Promise.allSettled verwenden:
Hinweis: Promise.allSettled wird niemals abgelehnt. Es löst sich immer mit einem array von Ergebnisobjekten auf, die jeweils eine status-Eigenschaft ('fulfilled' oder 'rejected') sowie entweder eine value- oder reason-Eigenschaft enthalten.
Diese Methode ist besonders nützlich, wenn sichergestellt werden soll, dass alle Promises bis zur Fertigstellung verarbeitet werden, unabhängig davon, ob sie erfüllt oder abgelehnt werden.
Promise.race implementieren
Promise.race ist ein weiteres leistungsstarkes Werkzeug, das die Verarbeitung mehrerer Promises ermöglicht, indem es sich auflöst oder ablehnt, sobald eines der Promises im Iterable aufgelöst oder abgelehnt wird.
Promise.race verwenden
Nachfolgend eine praktische Anwendung von Promise.race:
Diese Methode ist ideal für Szenarien, in denen das schnellste Ergebnis aus mehreren asynchronen Operationen benötigt wird — zum Beispiel beim Wettrennen einer Anfrage gegen ein Timeout-Promise. Zu beachten: race schließt ab beim ersten Promise, das sich abschließt, ob es erfüllt oder abgelehnt wird.
Den ersten Erfolg mit Promise.any erhalten
Promise.any ist das optimistische Gegenstück zu Promise.race. Es ignoriert Ablehnungen und löst sich mit dem Wert des ersten erfüllten Promises auf. Es lehnt nur ab, wenn jedes Promise abgelehnt wird — in diesem Fall wirft es einen AggregateError, dessen .errors-Eigenschaft alle einzelnen Ablehnungsgründe enthält.
Promise.any verwenden
Promise.any sollte verwendet werden, wenn mehrere Quellen für dieselben Daten vorhanden sind (z. B. Spiegelserver) und nur das erste erfolgreiche Ergebnis relevant ist.
Promises mit resolve und reject erstellen
Promise.resolve(value) und Promise.reject(reason) sind Abkürzungen zum Erstellen eines bereits abgeschlossenen Promises ohne den new Promise(executor)-Boilerplate.
Promise.resolve(value)gibt ein Promise zurück, das bereits mitvalueerfüllt ist. Wennvalueselbst ein Thenable ist, wird es „übernommen" und verfolgt.Promise.reject(reason)gibt ein Promise zurück, das bereits mitreasonabgelehnt ist.
Diese Hilfsmethoden werden häufig verwendet, um einen gecachten Wert aus einer ansonsten asynchronen Funktion zurückzugeben oder eine .then()-Kette zu starten.
Einen Polyfill für Promise.allSettled erstellen
Nicht alle Umgebungen unterstützen Promise.allSettled nativ. Daher kann die Implementierung eines Polyfills die Kompatibilität in verschiedenen JavaScript-Umgebungen sicherstellen.
Polyfill für Promise.allSettled
So lässt sich ein einfacher Polyfill erstellen:
Dieser Polyfill stellt eine grundlegende Funktionalität bereit, bei der jedes Promise einzeln behandelt und auf sein jeweiliges Ergebnis aufgelöst wird, sodass das allSettled-Verhalten effektiv nachgeahmt wird.
Durch die Integration dieser fortgeschrittenen Promise-Techniken und das Verständnis der zugrunde liegenden Mechanismen von Polyfills lässt sich JavaScript-Code auf ein neues Niveau heben. Diese Methoden verbessern nicht nur die Code-Zuverlässigkeit, sondern bieten auch eine verfeinerte Kontrolle über asynchrone Operationen und ebnen den Weg für robustere Webanwendungen.