Mit fetch() können Sie Netzwerkanfragen ähnlich wie XMLHttpRequest (XHR) stellen. Der Hauptunterschied besteht darin, dass die Fetch API Promises verwendet, die eine einfachere API haben, um die komplizierten Callbacks in der XMLHttpRequest API zu vermeiden.
Wenn Sie noch nie Promises verwendet haben, lesen Sie die Einführung in JavaScript-Promises.
Einfache Fetch-Anfrage
Hier ein Beispiel, das mit einem XMLHttpRequest und dann mit fetch implementiert wurde. Wir möchten eine URL anfordern, eine Antwort erhalten und diese als JSON parsen.
XMLHttpRequest
Für ein XMLHttpRequest sind zwei Listener erforderlich, um die Erfolgs- und Fehlerfälle zu verarbeiten, sowie ein Aufruf von open() und send().
Beispiel aus der MDN-Dokumentation
function reqListener () {
const data = JSON.parse(this.responseText);
console.log(data);
}
function reqError (err) {
console.log('Fetch Error :-S', err);
}
const 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(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(err => {
console.log('Fetch Error :-S', err);
});
Für die fetch()-Anfrage ist nur ein Aufruf erforderlich, um dieselbe Aufgabe wie im XHR-Beispiel auszuführen. Um die Antwort zu verarbeiten, prüfen wir zuerst, ob der Antwortstatus 200 ist, und parsen die Antwort dann als JSON. Die Antwort auf eine fetch()-Anfrage ist ein Stream-Objekt. Das bedeutet, dass nach dem Aufruf der Methode json() ein Promise zurückgegeben wird.
Der Stream erfolgt asynchron.
Antwortmetadaten
Im vorherigen Beispiel wurde der Status des Response-Objekts gezeigt 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(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, erhält die Antwort den response.type „basic“, „cors“ oder „opaque“. Diese types geben an, woher die Ressource stammt. Sie können sie verwenden, um zu bestimmen, wie das Antwortobjekt behandelt werden soll.
Wenn der Browser eine Ressource am selben Ursprung anfordert, hat die Antwort den Typ basic mit Einschränkungen, was Sie in der Antwort sehen können.
Wenn eine Anfrage für eine Ressource an einem anderen Ursprung gestellt wird und dieser Ursprung CORS-Header zurückgibt, ist der Typ cors. cors-Antworten ähneln basic-Antworten, beschränken jedoch die Header, die Sie sich ansehen können, auf Cache-Control, Content-Language, Content-Type, Expires, Last-Modified und Pragma.
opaque-Antworten stammen von einem anderen Ursprung, der keine CORS-Header zurückgibt. Bei einer intransparenten Antwort können wir die zurückgegebenen Daten nicht lesen und den Status der Anfrage nicht einsehen. Das bedeutet, dass Sie nicht prüfen können, 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-originist nur für Anfragen für Assets am selben Ursprung erfolgreich und lehnt alle anderen Anfragen ab.corslässt Anfragen für Assets am selben Ursprung und an anderen Ursprüngen zu, die die entsprechenden CORS-Header zurückgeben.cors-with-forced-preflightführt vor jeder Anfrage eine Preflight-Prüfung durch.no-corsist für Anfragen an andere Ursprünge gedacht, die keine CORS-Header haben und eineopaque-Antwort zurückgeben. Wie bereits erwähnt , ist dies derzeit im globalen Fensterbereich nicht möglich.
Wenn Sie den Modus festlegen möchten, fügen Sie ein Optionsobjekt als zweiten Parameter in der fetch-Anfrage hinzu und definieren Sie den Modus in diesem Objekt:
fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
.then(response => response.text())
.then(text => {
console.log('Request successful', text);
})
.catch(error => {
log('Request failed', error)
});
Promise-Chaining
Eine der besten Funktionen von Promises ist die Möglichkeit, sie miteinander zu verketten. Bei fetch() können Sie so Logik für verschiedene Abrufanfragen freigeben.
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 Promises zurückgeben, und die Abrufanfrage nur für die endgültigen Daten und den Fehlerfall verwenden.
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(data => {
console.log('Request succeeded with JSON response', data);
}).catch(error => {
console.log('Request failed', error);
});
In diesem Beispiel wird eine status-Funktion definiert, die 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 der erste Methodenaufruf in der fetch()-Kette.
Wenn das Promise aufgelöst wird, ruft das Script die Methode json() auf, die ein zweites Promise aus dem Aufruf response.json() zurückgibt und ein Objekt mit dem geparsten JSON-Code erstellt. Wenn das Parsen fehlschlägt, wird das Promise abgelehnt und die catch-Anweisung ausgeführt.
Mit dieser Struktur können Sie die Logik für alle Abrufanfragen freigeben, sodass der Code einfacher zu verwalten, zu lesen und zu testen ist.
POST-Anfrage
Manchmal muss eine Web-App 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 fetch()-Optionen fest:
fetch(url, {
method: 'post',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: 'foo=bar&lorem=ipsum'
})
.then(json)
.then(data => {
console.log('Request succeeded with JSON response', data);
})
.catch(error => {
console.log('Request failed', error);
});
Anmeldedaten mit einer Abrufanfrage senden
Wenn Sie eine Abrufanfrage mit Anmeldedaten wie Cookies stellen möchten, setzen Sie den Wert credentials der Anfrage auf "include":
fetch(url, {
credentials: 'include'
})