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

Beitrag lesen

Hallo Nico R.,

Ich unterstelle mal, dass dein sleep.php ein Dummy ist. Denn um 5s zu warten, braucht man keinen Servercode. Das geht mit setTimeout().,

Beste Lösung: verwende fetch statt XMLHttpRequest und nutze die Promises, die dabei herauskommen.

Zweitbeste Lösung: Bleibe bei XMLHttpRequest und initialisiere ein Promise, das Du im readyState 4 auf resolved setzt

Drittbeste Lösung: Ein Callback.

Code-Beispiele:

Eine warte()-Funktion in JavaScript, mit setTimeout und Promises. Das Beispiel im verlinkten Artikel ist umfangreicher und enthält eine Erweiterung, mit der man den Wartezyklus abbrechen kann. Aber um nur 5s zu warten...

function warte(millisecs) {
   return new Promise((resolve, reject) => {
      setTimeout(resolve, millisecs);
   });
}

warte(5000)
.then(button_einblenden);

Für Erklärungen schaue in den verlinkten Wiki-Artikel über Promises.

Für einen Server-Request kann man fetch() verwenden (eine unserer vor sich hin rottenden Baustellen im Wiki 😕).

fetch("sleep.php")
.then(response => {
  if (response.ok)
    // Hier die richtige Empfangsmethode für die Antwortdaten verwenden!
    return response.text();   
  else
    throw new Error('Serveraufruf war nicht erfolgreich!');
})
.then(wert => {
   // tu was mit dem Wert
   button_einblenden();
})
.catch(error => {
   // Fehlerbehandlung, der throw von oben landet auch hier
});

Interessant an Promises ist, dass jeder .then ein neues Promise zurückgibt, das sich erfüllt, sobald der Code im .then erfolgreich ausgeführt wurde. Äh, ok, das ist nur die halbe Wahrheit, der then-Callback kann auch seinerseits ein Promise zurückgeben und das then-Promise erfüllt sich dann, wenn das zurückgegebene Promise erfüllt wird. Der erste .then nach fetch tut genau das, response.text() liefert ein Promise, das sich erfüllt, sobald der Text komplett über's Netz geladen ist.

Durch diese Promise-Verkettung kann man eine Promise-Abfolge auch unterbrechen:

function datenHolen() {
   return fetch("data.php")
   .then(response => response.text());
}

datenHolen()
.then(text => /* tu was mit dem text */)

Und dann gibt's noch die gezuckerte Version, mit await und async:

async function datenHolen() {
   let response = await fetch("data.php");
   return await response.text();
}

// Folgender Code funktioniert nur in einer async-Funktion oder in
// einem ECMAScript-Modul (<script type="module">):

await datenHolen();
button_einblenden();

Gezuckert? await und async sind nichts weiter als ein callbackfreier Ersatz für die .then-Ketten von Promises, deswegen fällt das unter die Kategorie "Syntaxzucker".

Rolf

--
sumpsi - posui - obstruxi