Defered and Promises in jQuery

Ein Deferred-Objekt dient dazu bei Ausführung bestimmter Funktionen d es Deferred-Objekts wie resolve und reject bestimmte registrierte Handler auszuführen.

Grundsätzlich muss erstmal ein Deferred-Objekt erstellt werden.

Nun kann direkt auf diesem Objekt die Funktion resolve ausgeführt werden.

Das tut jetzt erstmal gar nichts, weil auf dem entsprechenden Deferred-Objekt kein Handler registriert ist, der auf das resolve reagiert. Aber das holen wir jetzt nach:

Der Aufruf deferred.resolve(„Hallo Welt“) der führt jetzt dazu, dass der registrierte Handler reagiert. Dabei übernimmt er den verwendeten Übergabeparameter. Die Verwendung mehrerer Parameter ist ebenso möglich.

Für deferred.resolve(„Hallo Welt“) können durchaus auch mehrere Handler registriert werden.

Hier als Beispiel ein zweiter Handler:

Auf diesem Deferred-Objekt kann neben resolve auch noch die die Funktion reject ausgeführt werden.

Die Handler für diese Funktion werden über fail registriert.

Man sieht hier schon, dass resolve für erfolgreiche Aktionen und reject eher für fehlerhafte Aktionen vorgesehen ist, obwohl das technisch nicht unbedingt so vorgegeben ist. Aber die Bezeichnungen der Funktionen geben in gewisser Weise schon vor, wie die Funktionen fachlich zu verwenden sind.

Nun gibt es noch eine weitere Art der Handler-Registrierung, nämlich über die Funktion then.

Hierbei werden die Handler für resolve und reject in einem Aufruf registriert. Die erste Funktion entspricht dabei dem Handler für resolve, die zweite dem Handler für reject.

Die bisherigen Ausführungen würden in der Praxis so keinen Sinn machen. Erst im Zusammenhang mit der asynchronen Programmierung wird einem klar, welchem Zweck Deferred und Promises eigentlich dienen.

Das nachfolgende Beispiel zeigt, wie man auf herkömmliche Art und Weise einen asynchronen callback-basierten Aufruf realisiert.

Hier werden der Funktion GetGitHubUserInfo beim Aufruf zwei Callback-Funktionen übergeben, die dann in der Funktion an den entsprechenden Stellen ausgeführt werden.

Das Ganze wandeln wir jetzt in einen Promise-basierten Aufruf um.

Hier ist die Funktion GetGitHubUserInfo so verändert, dass sie ein Deferred-Objekt erstellt und dort wo im Callback-basierten Ansatz die Callback-Methoden ausgeführt wurden, die Deferred-Funktionen resolve bzw. reject ausgeführt werden.

Die Handler für die erfolgreiche Ausführung (resolve) bzw. für den Fehlerfall (reject) werden nicht in der Funktion selber erstellt, sondern direkt an der aufrufenden Stelle, genau wie im Callback-basierten Ansatz.

Die Registierung der Handler wird im Promise-basierten Ansatz mit Hilfe des Promise-Objekts durchgeführt. Dieses Promise-Objekt gibt die Funktion der aufrufenden Stelle (return deferred.promise();). Und auf diesem Promise-Objekt können dann z.B. über die Funktion then Success und Error-Handler registriert werden. Auch die Verwendung von done und fail für die Registrierung der entsprechenden Handler wäre hier möglich.

Das Promise-Objekt ist eine Teilmenge des Deferred-Objektes. Das Promise-Objekt beinhaltet nur die Methoden, die zur Erstellung der Handler notwendig sind. Die Methoden resolve und reject lassen sich nicht über das Promise-Objekt ausführen.

Warum nun sollte man anstatt des Callback-basierten den Promise-basierten Ansatz wählen?

Aus meiner Sicht ist das wichtigste Argument für den Promise-basierten Ansatz das Chaining. Mit dem Chaining können auf einfache Art und Weise mehrere asynchrone Vorgänge in eine Reihenfolge gebracht werden, sie können also synchron abgearbeitet werden. Dabei können Parameter von einem Prozess an den nächsten weitergegeben werden.

Ein einfaches Beispiel soll dies verdeutlichen:

Durch die Bereitstellung des Rückgabewerts „return asyncMessage(„Nachricht 222″, 1000);“ entspricht der komplette Ausdruck

einem Promise-Objekt, auf dem dann wiederum ein then angewendet werden kann. Zu beachten ist aber hier, dass alle so verketteten Handler nacheinander abgearbeitet werden.

Man kann auch etwas anderes als ein Promise-Objekt zurückgeben, wie im obigen Beispiel return „Einfacher String“; . Dann wird dieser Werte in den Handler übergeben und dort direkt verarbeitet, weil man ja nicht auf ein resolve eines Deferred-Objekts warten muss.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.