dedlfix: AngualrJS $q

Beitrag lesen

Tach!

Ich hab deshalb keine Ahnung, was dieser Code unten macht:

Das ist ein Promise - das Versprechen, dass es ein Ergebnis geben wird, aber nicht jetzt, sondern später. Deshalb gibt die Funktion erstmal nur das Promise zurück. Irgendwann später wird es erfüllt oder zurückgewiesen. Vom Promise wird dazu entweder resolve() oder reject() aufgerufen, was letztlich dazu führt, dass bei dir die entsprechenden Callback-Funktionen aufgerufen werden, damit du dann mit dem Ergebnis oder der Fehlermeldung was anfangen kannst.

Die Funktion definiert nicht nur ein Promise für dich, sie nutzt ihrerseits mit dem Aufruf von getCurrentUserFromAPI() ein weiteres Promise, um dann mit dessen Ergebnis (success) oder Misserfolg (error) dein Promise zu erfüllen oder zurückzuweisen.

Man kommt nicht drumherum, bestimmte Sachen asynchron auszuführen. Zum Beispiel kommt ein Ajax-Aufruf erst irgendwann später wieder und man möchte nicht die ganze Zeit die UI blockieren. Deshalb verwendet man ein Promise als eine Art definierter Callbacks für den Gut- und Fehlerfall. Man muss sich dann aber auch im Klaren sein, dass man nun nicht mehr drumherum kommt und alles vom Ergebnis abhängige entweder in den Callbacks erledigt oder, wenn man selbst nur Mittelsmann ist, auch selbst ein Promise erstellen muss.

Wenn du mit Promises anfangen möchtest/musst, nimm erstmal einen Ajax-Aufruf, dann bist du nämlich nur Nutzer und musst kein Promise selbst erstellen. Das kommt erst hinzu, wenn du Mittelsmann-Funktionen schreiben willst, die das Ergebnis vor dem Zurückgeben bearbeiten - oder auch die Eingangswerte vor dem Aufrufen einer asynchronen Verarbeitung.

Das mit dem defer() ist die eine Schreibweise. Ich verwende immer die andere, weil ich da mit etwas weniger Code auskomme: Einmal return $q() aufrufen und eine Funktion übergeben, die mit resolve und reject zwei Funktionsreferenzen entgegennimmt. Der Rest (das was in der dem $q übergebenen Funktion stattfindet) ist dann das was die Aufgabenstellung erfordert.

function versprich_mir_was(irgendwelche_parameter) {
  return $q(function (resolve, reject) {

    var bearbeitete_parameter = bereite_vor(irgendwelche_parameter);

    ruf_eine_andere_funktion_auf_die_ein_promise_liefert(bearbeitete_parameter)
      .then(function (ergebnis) {
        var bearbeitetes_ergebnis = mach_was_mit_dem_ergebnis(ergebnis);
        resolve(bearbeitetes_ergebnis);
      })
      .catch(function (fehler) {
        console.log(fehler);
        reject(fehler);
      });
  });
}

In der Regel hat man selbst solchen Code, der ein anderes Promise nutzt, weil man irgendwelche asynchronen Dinge nutzen muss. Es ist kaum so, dass man selbst etwas Asynchrones neu aufsetzt. In den Beispielen wird immer gern mit einem Timeout gearbeitet, um eine Verzögerung darzustellen. In der Praxis wird die Nutzung von Promises meist wegen einer Ajax-Verwendung stattfinden. Ich hab aber auch schon einen Dialog in ein Promise gepackt. Der Dialog wird initialisiert und der Aufrufer bekommt nur ein Promise. Wenn der Anwender später den Dialog mit OK schließt, wird das Promise mit resolve() erfüllt und bei Abbruch mit reject() zurückgewiesen. An der Stelle der Verwendung ist das eine ziemlich übersichtliche Geschichte. Herkömmlich würde man Eventhandler für die Buttons schreiben und hätte eine Menge Code an der Stelle.

zeige_dialog(parameter)
  .then(function (ergebnis) {
    // tu was damit
  });
  // kein catch notwendig, wenn man bei Abbruch nichts machen möchte

dedlfix.