Rolf b: Promises & Callbacks

Beitrag lesen

Ich zerlege die übliche Aufrufkette mal in Fragmente:

var prom1 = new Promise(getResource);

var prom2 = prom1.done(function(data) {  // func1
   // brassel around in the DOM and fummle data hinein
});

prom2.catch(function(reason) { // func2
   alert("Das ging schief, weil HHTP Status " + reason); // ok, es gibt bessere Errorhandler
});

function getResource(fullfill, reject) {
   var request = new XMLHttpRequest();
   request.open("GET","daten.txt");}
   request.addEventListener('loadend', function(event) {
      if (request.status >= 200 && request.status < 300) {
         fulfill(request.responseText);
      } else if (request.status >= 300) {
         reject(request.status);
      }
});

Wo wird gewartet? Schaun wir mal.

Die getResource-Funktion - also der Executor des Promise - wird vom Konstruktor aufgerufen. Sie schickt den HTTP Request an den Server los und registriert den loadend Handler. Dann kehrt sie zurück, und prom1 enthält nun das erste Promise. Zeit gekostet hat das nicht viel.

Auf prom1 wird nun die done-Methode aufgerufen. Es ist damit zu rechnen, dass der HTTP Request noch eine ganze Weile auf der Leitung verbringt und noch nicht zurück ist. Also die an done übergeben Funktion in die Queue gestellt und ein neues Promise erstellt, dessen Status an das Aufrufergebnis dieser Funktion gekoppelt ist. Technisch ist das etwas vertrackter, wen's interessiert, mag die Spec lesen. Dieses Promise wird zurückgegeben. Die CPU ist nun ein paar Ticks älter, aber zum Popcorn rösten reicht es immer noch nicht.

Auf diesem zweiten Promise wird nun noch catch aufgerufen. Das erste Promise langweilt sich immer noch, das zweite Promise etwas weniger, weil's jünger ist, und lässt den Catch-callback nun an sich pendeln. Zum Spaß gibt die ein drittes Promise zurück, aber das brauchen wir nicht mehr. Zeit? Minimal.

Fertig - das Javascript endet und der XMLHttpRequest wartet nun friedlich auf die Serverantwort.

Irgendwann antwortet der Server und der loadend eventListener wird aktiv. Der ruft nun entweder fulfill oder reject auf und dann…

bei fulfill: prom1 wird erfüllt und die Function func1 wird aufgerufen. Diese gibt nichts zurück (also undefined), wodurch prom2 sich mit dem Erfüllungswert undefined erfüllt. prom2 hat keinen Handler dafür und tut weiter nichts, wodurch das vergessene prom3 sich auch erfüllt und der Ablauf endet

bei reject: prom1 wird zurückgewiesen. Da bei prom1.done(...) kein Reject-Callback mitgegeben wurde, führt das direkt zur Zurückweisung von prom2, woraufhin die registrierte catch-Funktion prom2 aufgerufen wird. Die bringt den alert und endet ohne Rückgabe, wodurch noch das vergessene prom3 mit Erfüllungswert undefined erfüllt wird (was aber keinen interessiert).

Zeit? Warten? Blockierendes Javascript? Nur bei Alert. Aber das war ja nur zum Spielen drin.

Rolf