Rolf b: Promises & Callbacks

Beitrag lesen

Also was Du da in Node und Mongo machst, davon hab ich ja keine Ahnung, aber rein theoretisch betrachtet sind Promises ein Konzept der funktionalen Programierung, das Eingang in ECMAScript gefunden hat.

Leider ist das Promise nur rudimentär in unserem Wiki beschrieben, da ist noch was zu tun. Mal gucken ob ich dazu komme. Unterscheiden muss man auch zwischen den ECMAScript 6 Promises, und diversen Vorläufern aus Javascript-Bibliotheken, die ähnliches tun (z.B. Deferred in jQuery).

Abstract: Promises formalisieren das Handling asynchroner Abläufe. Dazu nutzen sie Callback-Funktionen.

Langfassung:

Ein Promise in JavaScript ist eine formalisierte Vorgehensweise, um Reaktionen auf asynchrone Abläufe zu realisieren. Callbacks tauchen dabei als Implementierungsdetail auf. Ein Promise-Objekt bekommt einen Executor mit, der vom Promise-Konstruktor seinerseits zwei Callbacks ins Promise bekommt (resolve und reject). Der Executor tut irgendwas, und entscheidet am Ende, ob er den resolve oder reject Callback aufruft.

Dieser Teil ist Aufgabe des Promise-Lieferanten.

Nun zur Sicht des Promise-Empfängers. Der ruft irgendwas auf, was ein Promise zurückgibt. Dieses Promise gilt zunächst einmal - solange der Executor des Lieferanten weder resolve noch reject gerufen hat - als „pending“ - Antwort offen. Sobald der Executor eine der beiden Callbackfunktionen gerufen hat, ist das Promise entweder erfüllt (fulfilled) oder zurückgewiesen (rejected). MDN übersetzt hier „fehlgeschlagen“, weiß nicht was nun besser ist.

Um nun vom Lieferanten den versprochenen Wert zu erhalten, ruft der Empfänger die .done Methode auf dem Promise auf. Dieser übergibt er wieder eine Callback-Funktion, die vom Promise in dem Moment aufgerufen wird, wo das Promise sich erfüllt. Das, was der Executor an resolve() übergeben hat, wird nun an den done-Callback übergeben.

Um benachrichtigt zu werden, ob das Versprechen gebrochen wurde, gibt es noch die .catch-Methode, hier kann man einen Callback registrieren, der aufgerufen wird wenn der Zustand des Promise auf rejected wechselt.

Im Gegensatz zum klassischen Callback können einem Promise mehrere done-Handler übergeben werden. Diese bilden eine Queue, die (vermutlich) in Registrierungsreihenfolge abgearbeitet werden. Ein done-Handler kann seinerseits ein neues Promise zurückgeben, mit eigenem Executor, so dass man then-Aufrufe verketten kann.

promiseMe(executor1) .done(doneHandler1ThatReturnsPromise2) .done(doneHandler2ForPromise2);

Wie man sich das Chaos vorstellen soll, wenn auf ein Promise mehrere done-Handler registriert werden und jeder ein eigenes neues Promise zurückliefert, das müsste ich erstmal in Ruhe entwirren.

Spannend am Promise ist auch, dass es nach seiner Erstellung als Objekt existiert und weitergereicht werden kann. Jeder, der das Promise in die Hand bekommt, kann dann einen done- oder catch-Handler anhängen. Mit einem einfachen Callback-Mechanismus geht so etwas nicht.

Rolf