Dies ist nur eine Spielwiese.
Das echte SELFHTML-Wiki gibt es unter https://wiki.selfhtml.org.

JavaScript/Objekte/Promise

SELFHTML e.V.
Wechseln zu: Navigation, Suche

in arbeit

Das mit ECMAScript 2015 (ES6) eingeführte Konstruktorfunktion Promise dient zur Repräsentation asynchroner Vorgänge. Der asynchrone Vorgang wird eingeleitet durch eine Exekutor-Funktion, die der Promise-Konstruktor als Parameter erhält. Das Ergebnis ist über Callback-Funktionen abrufbar, die über die then und catch Methoden des Promise-Objekts registriert werden. Eine allgemeinere Einführung in Promises finden Sie hier. Für den Einsatz in älteren Browsern steht ein Polyfill zur Verfügung (siehe Weblinks).

Details: caniuse.com

Konstruktor

var promise = new Promise(executor);

Methoden

Methoden von Promise.prototype


Erzeugen eines Promise

Oft werden Promises nicht von Ihnen erzeugt. Viele JavaScript Bibliotheken geben Promises zurück, um Ihnen die Synchronisierung mit asynchronen Vorgängen zu ermöglichen, und neuere APIs wie z.B. [Service Worker] ebenfalls.

Wenn Sie ältere APIs in Promises kapseln wollen, erzeugen Sie das benötigte Promise-Objekt selbst. Dazu schreiben Sie eine Funktion, die die gewünschte asynchrone Operation auslöst und übergeben diese Funktion als Argument an den Promise-Konstruktor. Der Konstruktor führt diese Funktion sofort aus und übergibt Callbacks-Funktionen resolve und reject. Genau eine dieser beiden Callback-Funktionen müssen Sie irgendwann aufrufen, damit das Promise aus dem Schwebezustand pending herauskommt.

var executor = function(resolve, reject) {
   // ...
}

var promise = new Promise(executor);

In der Exekutor-Funktion müssen Sie die Rückmeldungen des ausgelösten asynchronen Vorgangs wie gewohnt entgegennehmen. Sie haben, wenn die Rückmeldung eintrifft, nun genau eine Reaktionsmöglichkeit. Ist der Vorgang erfolgreich gewesen, rufen Sie resolve(ergebnis) auf. Ist er fehlgeschlagen, rufen Sie reject(fehlergrund) auf. Was das Ergebnis oder der Fehlergrund nun genau ist, bleibt Ihnen überlassen. Das Promise stellt diese Werte unverändert als Ergebnis des Promise bereit. Dazu gleich mehr.

Zustände und Verhalten

Ein Promise ist in einem von drei grundlegenden Zuständen:

  • pending - Schwebezustand, der asynchrone Vorgang ist noch nicht beendet
  • fulfilled - Erfüllt, der asynchrone Vorgang war erfolgreich
  • rejected - Zurückgewiesen, der asynchrone Vorgang ist gescheitert

Die Zustände fulfilled und rejected werden auch unter dem Oberbegriff settled zusammengefasst.

Zustandswechsel sind nur von pending nach fulfilled oder von pending nach rejected möglich. Sobald ein Promise settled ist, werden weitere Aufrufe der resolve oder reject Callbacks ignoriert. Darüber hinaus kann ein Promise auch gesperrt werden. Es erhält seinen Wert dann indirekt durch ein anderes Promise. Eine solche Sperrung erfolgt unter bestimmten Bedingungen implizit, eine Methode wie lock gibt es nicht.

Um den Wert, mit dem ein Promise erfüllt oder zurückgewiesen wird, abzuholen, stellt Promise.prototype zwei Methoden bereit: then und catch. Catch dient der Lesbarkeit und Bequemlichkeit, folgende Aufrufe bewirken das Gleiche:

promise.catch(rejectHandler);
promise.then(null, rejectHandler);

Die then Methode erwartet zwei Parameter, deren Argumente Funktionen oder null sein müssen: einen fulfillHandler und einen rejectHandler. Die fulfillHandler werden für erfüllte Promises aufgerufen und bekommen den Erfüllungswert des Promise als Parameter übergeben. Analog werden die rejectHandler für zurückgewiesene Promises aufgerufen und bekommen den Zurückweisungsgrund übergeben.

Die übergebenen Handler werden nie synchron aufgerufen. Statt dessen definiert ES6 eine PromiseJob Queue, in die die Handler als PromiseJob eingestellt werden. Die Queue wird abgearbeitet, wenn das aktuell laufende Skript endet.

Eine andere Frage ist, wann die PromiseJobs in die Queue gelangen. Dazu sind zwei Fälle zu unterscheiden.

then und catch bei einem pending Promise

Solange das Promise auf pending steht, gelangen die fulfill- und rejectHandler nicht in die PromiseJob Queue. Statt dessen speichert das Promise sie beim Aufruf von then oder code>catch</code> in internen Listen zwischen. Wird null statt einer Funktion übergeben, wird nichts gespeichert.

then und catch bei einem settled Promise

Ist das Promise nicht mehr im pending Status, findet keine Zwischenspeicherung mehr statt. Die erforderlichen PromiseQueue Jobs werden sofort erstellt.

Gemeinsame Verhaltensweise

In beiden Fällen geben then und catch ein neues Promise P2 zurück. P2 hat keine Exekutor-Funktion, sondern ist gesperrt und zunächst im pending Zustand. Der PromiseJob, der zuvor in die PromiseJob Queue eingestellt wurden, kennt dieses Promise. Sobald der Job gelaufen ist, wird der Rückgabewert der Handler-Funktion ausgewertet und davon abhängig P2 auf resolved oder rejected gesetzt.

  • Ist die Handler-Funktion null, so wird der Zustand des ursprünglichen Promise auf P2 übertragen.
  • Gibt die Handler-Funktion ein weiteres Promise P3 zurück, so wird P2 an P3 gebunden, d. h. der Zustand von P2 folgt dem von P3.
  • Gibt die Handler-Funktion irgendeinen anderen Wert zurück, so wird P2 erfüllt und der zurückgegebene Wert als sein Erfüllungswert gesetzt.
  • Wirft die Handler-Funktion eine Exception, so wird P2 zurückgewiesen und die Exception wird zum Zurückweisungsgrund.

... wird fortgesetzt


Weblinks

  • [1] Polyfill für ES6 Promises