Rolf B: Wie PHP Error Message clientseitig [korrekt] auffangen?

Beitrag lesen

Hallo Helge,

eigentlich hast Du nur einen kleinen Fehler drin:

throw new Error(res.text());

res.text() liefert nicht den Text, sondern ein Promise für den Text. Das ist deshalb so, weil das von fetch gelieferte Promise bereits resolved, sobald der Browser die http-Header vorfindet. Der eigentliche Body ist ggf. noch gar nicht da.

Du musst den Error also mit dem werfen, was aus dem res.text() Promise herauskommt.

fetch(url)    // -> Promise A
.then(response => {                             // then-1
  if (response.ok)
    return response.text();                     // -> Promise E
  else
    return response
            .text()                             // -> Promise F
            .then(msg => throw new Error(msg)); // then-3
                                                // -> Promise G
})            // -> Promise B
.then(text => {                                 // then-2
   ...
})            // -> Promise C
.catch(error => {
   ...
});           // -> Promise D

Die Promise-Flut bei fetch ist nicht ganz einfach zu durchschauen. fetch liefert ein Promise A. Auf Promise A wird then-1 aufgerufen und liefert ein NEUES Promise: Promise B. Auf B wird then-2 aufgerufen, heraus kommt Promise C, und darauf wird catch aufgerufen. Auch catch liefert wieder ein Promise - aber dieses wird im Beispiel nicht weiter verwendet.

All das passiert, während der Browser gerade erst den Request zum Server schickt. Nachdem catch sein Promise D zurückgegeben hat, läuft JavaScript weiter.

Irgendwann trifft die Antwort vom Server ein und Promise A erfüllt sich (es sei denn, der Server antwortet nicht, dann wird es rejected - was auch Promise B rejected, was Promise C rejected, was den Callback bei catch() aufruft).

Wird Promise A resolved, läuft der Callback von then-1 an. Der prüft den response-Status und ruft nun response.text() auf. Daraus entsteht nun ein neues Promise E oder F, je nach Codezweig.

Im ok-Zweig wird Promise E direkt zurückgegeben, was die Erfüllung von Promise B an die Erfüllung von Promise E koppelt. Der Callback von then-2 liefert deshalb den Text, zu dem Promise E resolved wird.

Wenn response.ok nicht gesetzt ist, wird ebenfalls response.text() aufgerufen, was ein Promise F liefert, aber hierauf wird nun gleich das then-3 aufgerufen. Das ergibt ein Promise G, was aus dem then-1 zurückgegeben wird. Im Fehlerfall ist also nun der Erfolg von Promise B an den Erfolg von Promise G gekoppelt.

Das then-3 ist aber nun so geschrieben, dass es den Text von Promise F entgegen nimmt und ihn als Error wirft. Eine Exception im then-Callback führt zum Reject des Promise G, was ebenfalls Promise B rejected. Weil C an B gekoppelt ist, rejected nun auch Promise C und catch ruft seinen Callback auf, in dem das Error-Objekt ankommt.

Kompliziert? Yup!

Rolf