Einführung in "fetch()"

Matt Gaunt

Mit fetch() können Sie Netzwerkanfragen ähnlich wie XMLHttpRequest (XHR) senden. Der Hauptunterschied besteht darin, dass die Fetch API Promises verwendet, eine einfachere API, mit der Sie die komplizierten Callbacks in der XMLHttpRequest API vermeiden können.

Unterstützte Browser

  • 42
  • 14
  • 39
  • 10.1

Quelle

Wenn Sie Promise-Objekte noch nie verwendet haben, sollten Sie die Einführung in JavaScript-Promise-Objekte lesen.

Einfache Abrufanfrage

Hier ist ein Beispiel, das mit einem XMLHttpRequest und dann mit fetch implementiert wurde. Wir möchten eine URL anfordern, eine Antwort erhalten und sie als JSON parsen.

XMLHttpRequest

Ein XMLHttpRequest benötigt zwei Listener, um die Erfolgs- und Fehlerfälle zu verarbeiten, sowie einen Aufruf von open() und send(). Beispiel aus MDN-Dokumenten

function reqListener() {
    var data = JSON.parse(this.responseText);
    console.log(data);
}

function reqError(err) {
    console.log('Fetch Error :-S', err);
}

var oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();

Abrufen

Unsere Abrufanfrage sieht so aus:

fetch('./api/some.json')
  .then(
  function(response) {
    if (response.status !== 200) {
      console.log('Looks like there was a problem. Status Code: ' +
        response.status);
      return;
    }

    // Examine the text in the response
    response.json().then(function(data) {
      console.log(data);
    });
  }
  )
  .catch(function(err) {
    console.log('Fetch Error :-S', err);
  });

Die fetch()-Anfrage benötigt nur einen Aufruf, um dieselbe Arbeit wie im XHR-Beispiel auszuführen. Zur Verarbeitung der Antwort prüfen wir zuerst, ob der Antwortstatus 200 lautet, und parsen die Antwort dann als JSON. Die Antwort auf eine fetch()-Anfrage ist ein Stream-Objekt. Das bedeutet, dass nach dem Aufrufen der json()-Methode ein Promise-Objekt zurückgegeben wird. Der Stream erfolgt asynchron.

Antwortmetadaten

Das vorherige Beispiel zeigte den Status des Response-Objekts und wie die Antwort als JSON geparst wird. So gehen Sie mit anderen Metadaten um, auf die Sie möglicherweise zugreifen möchten, z. B. Header:

fetch('users.json').then(function(response) {
    console.log(response.headers.get('Content-Type'));
    console.log(response.headers.get('Date'));

    console.log(response.status);
    console.log(response.statusText);
    console.log(response.type);
    console.log(response.url);
});

Antworttypen

Wenn wir eine Abrufanfrage stellen, wird als Antwort als response.typebasic“, „cors“ oder „opaque“ zurückgegeben. Diese types geben an, woher die Ressource stammt, und Sie können sie verwenden, um festzulegen, wie das Antwortobjekt zu behandeln ist.

Wenn der Browser eine Ressource vom selben Ursprung anfordert, hat die Antwort den Typ basic mit Einschränkungen dafür, was Sie in der Antwort sehen können.

Wenn eine Anfrage für eine Ressource an einem anderen Ursprung gesendet wird und dieser Ursprung CORs-Header zurückgibt, ist der Typ cors. cors-Antworten ähneln basic-Antworten, beschränken jedoch die Header, die Sie ansehen können, auf Cache-Control, Content-Language, Content-Type, Expires, Last-Modified und Pragma.

opaque-Antworten stammen aus einem anderen Ursprung, der keine CORS-Header zurückgibt. Bei einer intransparenten Antwort können wir die zurückgegebenen Daten nicht lesen oder den Status der Anfrage einsehen, d. h., Sie können nicht prüfen, ob die Anfrage erfolgreich war.

Sie können einen Modus für eine Abrufanfrage definieren, sodass nur bestimmte Anfragetypen aufgelöst werden. Folgende Modi können festgelegt werden:

  • same-origin ist nur bei Anfragen für Assets desselben Ursprungs erfolgreich und lehnt alle anderen Anfragen ab.
  • cors lässt Anfragen für Assets desselben und anderer Ursprünge zu, die die entsprechenden CORs-Header zurückgeben.
  • cors-with-forced-preflight führt eine Preflight-Prüfung durch, bevor eine Anfrage gestellt wird.
  • no-cors ist dazu vorgesehen, Anfragen an andere Ursprünge zu senden , die keine CORS-Header haben und zu einer opaque-Antwort führen. Dies ist jedoch derzeit im globalen Fensterbereich nicht möglich.

Um den Modus zu definieren, fügen Sie in der fetch-Anfrage ein Optionsobjekt als zweiten Parameter hinzu und definieren den Modus in diesem Objekt:

fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
    .then(function(response) {
    return response.text();
    })
    .then(function(text) {
    console.log('Request successful', text);
    })
    .catch(function(error) {
    log('Request failed', error)
    });

Verkettung von Versprechen

Eins der großartigen Merkmale von Versprechen ist die Fähigkeit, sie miteinander zu verknüpfen. So können Sie für fetch() die Logik für Abrufanfragen gemeinsam nutzen.

Wenn Sie mit einer JSON API arbeiten, müssen Sie den Status prüfen und den JSON-Code für jede Antwort parsen. Sie können Ihren Code vereinfachen, indem Sie den Status und das JSON-Parsing in separaten Funktionen definieren, die Promise zurückgeben, und die Abrufanfrage verwenden, um nur die endgültigen Daten und den Fehlerfall zu verarbeiten.

function status(response) {
    if (response.status >= 200 && response.status < 300) {
    return Promise.resolve(response)
    } else {
    return Promise.reject(new Error(response.statusText))
    }
}

function json(response) {
    return response.json()
}

fetch('users.json')
    .then(status)
    .then(json)
    .then(function(data) {
    console.log('Request succeeded with JSON response', data);
    }).catch(function(error) {
    console.log('Request failed', error);
    });

In diesem Beispiel wird eine status-Funktion definiert, die response.status prüft und entweder ein aufgelöstes Promise als Promise.resolve() oder ein abgelehntes Promise als Promise.reject() zurückgibt. Dies ist die erste Methode, die in der fetch()-Kette aufgerufen wird.

Wenn das Promise aufgelöst wird, ruft das Skript die Methode json() auf, die ein zweites Promise aus dem response.json()-Aufruf zurückgibt und ein Objekt erstellt, das die geparste JSON-Datei enthält. Wenn das Parsing fehlschlägt, wird das Promise-Objekt abgelehnt und die Catch-Anweisung ausgeführt.

Mit dieser Struktur können Sie die Logik für alle Abrufanfragen freigeben, sodass Code einfacher verwaltet, gelesen und getestet werden kann.

POST-Anfrage

Manchmal muss eine Webanwendung eine API mit einer POST-Methode aufrufen und einige Parameter in den Text der Anfrage einfügen. Legen Sie dazu die Parameter method und body in den Optionen fetch() fest:

fetch(url, {
    method: 'post',
    headers: {
        "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
    },
    body: 'foo=bar&lorem=ipsum'
    })
    .then(json)
    .then(function (data) {
    console.log('Request succeeded with JSON response', data);
    })
    .catch(function (error) {
    console.log('Request failed', error);
    });

Anmeldedaten mit einer Abrufanfrage senden

Für eine Abrufanfrage mit Anmeldedaten wie Cookies setzen Sie den Wert credentials der Anfrage auf "include":

fetch(url, {
    credentials: 'include'
})