Rolf B: Grundsätzliche Frage. Ist ein Callback hier der richtige Ansatz?

Beitrag lesen

Hallo Nico R.,

Ließe sich das mit Promises klüger bewerkstelligen?

Ja. Promises haben concurrency-Methoden.

let p1 = fetchText("res1").then(processText1);
let p2 = fetchText("res2").then(processText2);

Promise.allSettled([p1, p2])
.then(button_einblenden);

Auf fetchText gehe ich gleich ein. Sie liefert ein Promise, sobald der Text verfügbar ist.

„Settled“ ist der Promise-Oberbegriff für resolved oder rejected. Die Promise.allSettled-Methode erzeugt ein neues Promise, das die an allSettled übergebenen Promises „bündelt“. Wenn alle Promises aus diesem Bündel resolved oder rejected wurden, resolved sich das Bündel-Promise. Der then-Handler bekommt ein Array mit allen Ergebnissen, für Details muss ich auf die MDN verweisen.

Wenn Du in den Verarbeitungsfunktionen processText1 und processText2 fertig bist, werden p1 und p2 resolved, und der Button erscheint. Letztlich passiert da genau das, was Du Dir schon selbst überlegt hast - aber so ist das Rad fertig und braucht keinen neuen Erfinder.

fetchText wäre mein Vorschlag für eine Funktion, die den Aufruf von fetch und den ersten .then-Handler bündelt, in dem Du den Erfolg der Operation abfragst.

Vorhin habe ich das als kleine Pfeilfunktion notiert:

.then(response => response.text())

aber das ist natürlich nicht produktionsreif. Unser Wiki zeigt auf der Seite für fetch ein etwas besseres Errorhandling. Den HTTP Status abzufragen kann man sich im ok-Fall sparen, ok ist nur true wenn der Status im 2xx-Bereich liegt (-> MDN)

Zum Beispiel so:

async function fetchText(ressource) {
   let response = await fetch(ressource);

   if (response.ok)
      return response.text();

   throw new Error("Fehler beim Laden von " + ressource);
}

Wenn Du nicht Text, sondern JSON vom Server bekommst, dann verwendest Du natürlich response.json() statt response.text(), um gleich das dekodierte Objekt zu erhalten, und nennst die Funktion fetchObject oder so.

Statt auf das allSettled-Promise mit then zu reagieren könnte man ebenfalls await verwenden, das hat aber die genannten Voraussetzungen (in async-Funktion notiert oder ein ECMAScript-Modul)

Beachte, dass die then-Callbacks nie zur gleichen Zeit aufgerufen werden, wenn der then läuft. D.h. direkt hinter dem then hast Du das Ergebnis der Operation, die ein Promise liefert, keinesfalls zur Verfügung. Die then-Callbacks werden grundsätzlich in der sogenannten Mikrotask-Queue ausgeführt, und das heißt: nach dem Ende des "normalen" JavaScript-Codes und vor dem Beginn der Layout-Phase des Browsers. async und await kaschieren das, aber auch da ist es so, dass aller Code, der den Rückgabewert eines await verarbeitet, in der Mikrotask-Queue ausgeführt wird.

Rolf

--
sumpsi - posui - obstruxi