Web APIs - Fetch-API: Verwenden von Fetch (2024)

Der Fetch API bietet eine JavaScript -Schnittstelle für den Zugriff auf und die Bearbeitung von Teilen des protocol , wie z. B. Anfragen und Antworten. Es bietet außerdem eine globale fetch() -Methode, die eine einfache und logische Möglichkeit bietet, Ressourcen asynchron über das Netzwerk abzurufen.

Im Gegensatz zu XMLHttpRequest , einer Callback-basierten API, basiert Fetch auf Versprechen und bietet eine bessere Alternative, die problemlos in service workers verwendet werden kann. Fetch integriert auch erweiterte HTTP-Konzepte wie CORS und andere Erweiterungen von HTTP.

Eine einfache Abrufanfrage sieht so aus:

js

async function logMovies() { const response = await fetch("http://example.com/movies.json"); const movies = await response.json(); console.log(movies);}

Hier rufen wir eine JSON-Datei über das Netzwerk ab, analysieren sie und geben die Daten auf der Konsole aus. Die einfachste Verwendung von fetch() verwendet ein Argument – ​​den Pfad zu der Ressource, die Sie abrufen möchten – und gibt nicht direkt den JSON-Antworttext zurück, sondern ein promise , das mit einem Response -Objekt aufgelöst wird.

Das Response -Objekt wiederum enthält nicht direkt den eigentlichen JSON-Antworttext, sondern ist stattdessen eine Darstellung der gesamten HTTP-Antwort. Um den JSON-Textinhalt aus dem Response -Objekt zu extrahieren, verwenden wir die Methode json() , die einen zweiten promise zurückgibt, der mit dem Ergebnis der Analyse des Antworttexts als JSON aufgelöst wird.

Hinweis: Ähnliche Methoden zum Extrahieren anderer Arten von Körperinhalten finden Sie im Abschnitt Body .

Abrufanforderungen werden durch die connect-src -Direktive von Content Security Policy und nicht durch die Direktive der abgerufenen Ressourcen gesteuert.

Bereitstellung von Anfrageoptionen

Die fetch() -Methode kann optional einen zweiten Parameter akzeptieren, ein init -Objekt, mit dem Sie eine Reihe verschiedener Einstellungen steuern können:

Die vollständigen verfügbaren Optionen und weitere Einzelheiten finden Sie unter fetch() .

js

// Beispielimplementierung der POST-Methode:async function postData(url = "", data = {}) { // Standardoptionen sind mit * markiert const response = await fetch(url, { method: "POST", // *GET, POST, PUT, DELETE usw. mode: "cors", // no-cors, *cors, same-origin cache: "no-cache", // *Standard, kein Cache, neu laden, Cache erzwingen, nur wenn zwischengespeichert credentials: "same-origin", // include, *same-origin, omit headers: { "Content-Type": "application/json", // 'Content-Type': 'application/x-www-form-urlencoded', }, redirect: "follow", // Handbuch, *folgen, Fehler referrerPolicy: "no-referrer", // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url body: JSON.stringify(data), // Der Körperdatentyp muss mit dem "Content-Type" -Header übereinstimmen }); return response.json(); // analysiert die JSON-Antwort in native JavaScript -Objekte}postData("https://example.com/answer", { answer: 42 }).then((data) => { console.log(data); // JSON-Daten werden durch den Aufruf „data.json()“ analysiert});

Beachten Sie, dass mode: "no-cors" nur einen begrenzten Satz von Headern in der Anfrage zulässt:

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type mit einem Wert von application/x-www-form-urlencoded , multipart/form-data oder text/plain

Ein Abruf wird abgebrochen

Um unvollständige fetch() -Vorgänge abzubrechen, verwenden Sie die Schnittstellen AbortController und AbortSignal .

js

const controller = new AbortController();const signal = controller.signal;const url = "video.mp4";const downloadBtn = document.querySelector("#download");const abortBtn = document.querySelector("#abort");downloadBtn.addEventListener("click", async () => { try { const response = await fetch(url, { signal }); console.log("Download complete", response); } catch (error) { console.error(`Download error: ${error.message}`); }});abortBtn.addEventListener("click", () => { controller.abort(); console.log("Download aborted");});

Senden einer Anfrage mit Anmeldeinformationen

Um Browser zu veranlassen, eine Anfrage mit Anmeldeinformationen zu senden, die sowohl bei Aufrufen mit demselben Ursprung als auch bei Aufrufen zwischen verschiedenen Ursprüngen enthalten sind, fügen Sie credentials: 'include' zum init -Objekt hinzu, das Sie an die Methode fetch() übergeben.

js

fetch("https://example.com", { credentials: "include",});

Hinweis: Access-Control-Allow-Origin darf keinen Platzhalter für Anfragen mit credentials: 'include' verwenden. In solchen Fällen muss die genaue Herkunft angegeben werden; Selbst wenn Sie eine CORS-Unblocker-Erweiterung verwenden, schlagen die Anforderungen dennoch fehl.

Hinweis: Browser sollten unabhängig von dieser Einstellung keine Anmeldeinformationen in Preflight-Anfragen senden. Weitere Informationen finden Sie unter: CORS Requests with credentials .

Wenn Sie Anmeldeinformationen nur senden möchten, wenn die Anforderungs-URL denselben Ursprung hat wie das aufrufende Skript, fügen Sie credentials: 'same-origin' hinzu.

js

// Das aufrufende Skript befindet sich im Ursprung „https://example.com“.fetch("https://example.com", { credentials: "same-origin",});

Um stattdessen sicherzustellen, dass Browser keine Anmeldeinformationen in die Anfrage aufnehmen, verwenden Sie credentials: 'omit' .

js

fetch("https://example.com", { credentials: "omit",});

Hochladen von JSON-Daten

Verwenden Sie fetch() , um JSON-codierte Daten zu posten.

js

async function postJSON(data) { try { const response = await fetch("https://example.com/profile", { method: "POST", // oder 'PUT' headers: { "Content-Type": "application/json", }, body: JSON.stringify(data), }); const result = await response.json(); console.log("Success:", result); } catch (error) { console.error("Error:", error); }}const data = { username: "example" };postJSON(data);

Hochladen einer Datei

Dateien können mit den HTML-Eingabeelementen <input type="file" /> , FormData() und fetch() hochgeladen werden.

js

async function upload(formData) { try { const response = await fetch("https://example.com/profile/avatar", { method: "PUT", body: formData, }); const result = await response.json(); console.log("Success:", result); } catch (error) { console.error("Error:", error); }}const formData = new FormData();const fileField = document.querySelector('input[type="file"]');formData.append("username", "abc123");formData.append("avatar", fileField.files[0]);upload(formData);

Mehrere Dateien hochladen

Dateien können mit den HTML-Eingabeelementen <input type="file" multiple /> , FormData() und fetch() hochgeladen werden.

js

async function uploadMultiple(formData) { try { const response = await fetch("https://example.com/posts", { method: "POST", body: formData, }); const result = await response.json(); console.log("Success:", result); } catch (error) { console.error("Error:", error); }}const photos = document.querySelector('input[type="file"][multiple]');const formData = new FormData();formData.append("title", "My Vegas Vacation");for (const [i, photo] of Array.from(photos.files).entries()) { formData.append(`photos_${i}`, photo);}uploadMultiple(formData);

Zeile für Zeile eine Textdatei bearbeiten

Die aus einer Antwort gelesenen Blöcke sind an den Zeilengrenzen nicht sauber unterteilt und sind Uint8Arrays, keine Zeichenfolgen. Wenn Sie eine Textdatei abrufen und Zeile für Zeile verarbeiten möchten, liegt es an Ihnen, diese Komplikationen in den Griff zu bekommen. Das folgende Beispiel zeigt eine Möglichkeit, dies zu erreichen, indem ein Zeileniterator erstellt wird (der Einfachheit halber wird davon ausgegangen, dass der Text UTF-8 ist und keine Abruffehler verarbeitet werden).

js

async function* makeTextFileLineIterator(fileURL) { const utf8Decoder = new TextDecoder("utf-8"); const response = await fetch(fileURL); const reader = response.body.getReader(); let { value: chunk, done: readerDone } = await reader.read(); chunk = chunk ? utf8Decoder.decode(chunk) : ""; const newline = /\r?\n/gm; let startIndex = 0; let result; while (true) { const result = newline.exec(chunk); if (!result) { if (readerDone) break; const remainder = chunk.substr(startIndex); ({ value: chunk, done: readerDone } = await reader.read()); chunk = remainder + (chunk ? utf8Decoder.decode(chunk) : ""); startIndex = newline.lastIndex = 0; continue; } yield chunk.substring(startIndex, result.index); startIndex = newline.lastIndex; } if (startIndex < chunk.length) { // Letzte Zeile endete nicht mit einem Zeilenumbruch char yield chunk.substr(startIndex); }}async function run() { for await (const line of makeTextFileLineIterator(urlOfFile)) { processLine(line); }}run();

Es wird überprüft, ob der Abruf erfolgreich war

Ein fetch() promise lehnt zusammen mit einem TypeError ab, wenn ein Netzwerkfehler auftritt oder CORS auf der Serverseite falsch konfiguriert ist, obwohl dies normalerweise auf Berechtigungsprobleme oder ähnliches zurückzuführen ist – ein 404-Fehler stellt beispielsweise keinen Netzwerkfehler dar. Eine genaue Prüfung für einen erfolgreichen fetch() würde die Prüfung umfassen, ob promise aufgelöst wurde, und dann prüfen, ob die Response.ok -Eigenschaft den Wert „true“ hat. Der Code würde etwa so aussehen:

js

async function fetchImage() { try { const response = await fetch("flowers.jpg"); if (!response.ok) { throw new Error("Network response was not OK"); } const myBlob = await response.blob(); myImage.src = URL.createObjectURL(myBlob); } catch (error) { console.error("There has been a problem with your fetch operation:", error); }}

Bereitstellung Ihres eigenen Anforderungsobjekts

Anstatt im fetch() -Aufruf einen Pfad zu der Ressource zu übergeben, die Sie anfordern möchten, können Sie mit dem Request() -Konstruktor ein Anforderungsobjekt erstellen und dieses als fetch() -Methodenargument übergeben:

js

async function fetchImage(request) { try { const response = await fetch(request); if (!response.ok) { throw new Error("Network response was not OK"); } const myBlob = await response.blob(); myImage.src = URL.createObjectURL(myBlob); } catch (error) { console.error("Error:", error); }}const myHeaders = new Headers();const myRequest = new Request("flowers.jpg", { method: "GET", headers: myHeaders, mode: "cors", cache: "default",});fetchImage(myRequest);

Request() akzeptiert genau die gleichen Parameter wie die fetch() -Methode. Sie können sogar ein vorhandenes Anforderungsobjekt übergeben, um eine Kopie davon zu erstellen:

js

const anotherRequest = new Request(myRequest, myInit);

Dies ist sehr nützlich, da Anforderungs- und Antworttexte nur einmal verwendet werden können. Wenn Sie eine solche Kopie erstellen, können Sie die Anfrage/Antwort effektiv erneut verwenden und bei Bedarf die init -Optionen variieren. Die Kopie muss erstellt werden, bevor der Text gelesen wird.

Hinweis: Es gibt auch eine clone() -Methode, die eine Kopie erstellt. Beide Methoden zum Erstellen einer Kopie schlagen fehl, wenn der Hauptteil der ursprünglichen Anfrage oder Antwort bereits gelesen wurde. Das Lesen des Hauptteils einer geklonten Antwort oder Anfrage führt jedoch nicht dazu, dass diese im Original als gelesen markiert wird.

Headers

Mit der Headers -Schnittstelle können Sie über den Headers() -Konstruktor Ihr eigenes Header-Objekt erstellen. Ein Header-Objekt ist eine einfache Mehrfachzuordnung von Namen zu Werten:

js

const content = "Hello World";const myHeaders = new Headers();myHeaders.append("Content-Type", "text/plain");myHeaders.append("Content-Length", content.length.toString());myHeaders.append("X-Custom-Header", "ProcessThisImmediately");

Dasselbe kann erreicht werden, indem ein Array von Arrays oder ein Objektliteral an den Konstruktor übergeben wird:

js

const myHeaders = new Headers({ "Content-Type": "text/plain", "Content-Length": content.length.toString(), "X-Custom-Header": "ProcessThisImmediately",});

Die Inhalte können abgefragt und abgerufen werden:

js

console.log(myHeaders.has("Content-Type")); // trueconsole.log(myHeaders.has("Set-Cookie")); // falsemyHeaders.set("Content-Type", "text/html");myHeaders.append("X-Custom-Header", "AnotherValue");console.log(myHeaders.get("Content-Length")); // 11console.log(myHeaders.get("X-Custom-Header")); // ['ProcessThisImmediately', 'AnotherValue']myHeaders.delete("X-Custom-Header");console.log(myHeaders.get("X-Custom-Header")); // null

Einige dieser Vorgänge sind nur in ServiceWorkers nützlich, bieten jedoch eine viel bessere API zum Bearbeiten von Headern.

Alle Header-Methoden lösen einen TypeError aus, wenn ein Header-Name verwendet wird, der kein gültiger HTTP-Header-Name ist. Die Mutationsoperationen lösen einen TypeError aus, wenn ein unveränderlicher Wächter ( see below ) vorhanden ist. Andernfalls scheitern sie stillschweigend. Zum Beispiel:

js

const myResponse = Response.error();try { myResponse.headers.set("Origin", "http://mybank.com");} catch (e) { console.log("Cannot pretend to be a bank!");}

Ein guter Anwendungsfall für Header ist die Überprüfung, ob der Inhaltstyp korrekt ist, bevor Sie ihn weiterverarbeiten. Zum Beispiel:

js

async function fetchJSON(request) { try { const response = await fetch(request); const contentType = response.headers.get("content-type"); if (!contentType || !contentType.includes("application/json")) { throw new TypeError("Oops, we haven't got JSON!"); } const jsonData = await response.json(); // Ihre Daten weiterverarbeiten } catch (error) { console.error("Error:", error); }}

Guard

Da Header in Anfragen gesendet und in Antworten empfangen werden können und es verschiedene Einschränkungen hinsichtlich der veränderbaren Informationen gibt, verfügen Header-Objekte über eine Guard-Eigenschaft. Dies wird nicht im Web angezeigt, wirkt sich jedoch darauf aus, welche Mutationsoperationen für das Header-Objekt zulässig sind.

Mögliche Schutzwerte sind:

  • none: default.
  • request : Schutz für ein Header-Objekt, das aus einer Anfrage erhalten wurde ( Request.headers ).
  • request-no-cors : Schutz für ein Header-Objekt, das aus einer mit Request.mode no-cors erstellten Anfrage erhalten wurde.
  • response : Schutz für ein Header-Objekt, das aus einer Antwort erhalten wurde ( Response.headers ).
  • immutable : Wächter, der ein Header-Objekt schreibgeschützt macht; Wird hauptsächlich für Servicemitarbeiter verwendet.

Hinweis: Sie dürfen den Content-Length -Header nicht an ein geschütztes Header-Objekt für einen response anhängen oder festlegen. Ebenso ist das Einfügen von Set-Cookie in einen Antwortheader nicht zulässig: ServiceWorker dürfen keine Cookies über synthetisierte Antworten setzen.

Response objects

Wie Sie oben gesehen haben, werden Response -Instanzen zurückgegeben, wenn fetch() promises aufgelöst werden.

Die am häufigsten verwendeten Antworteigenschaften sind:

  • Response.status – Eine Ganzzahl (Standardwert 200), die den Antwortstatuscode enthält.
  • Response.statusText – Eine Zeichenfolge (Standardwert „“), die der HTTP-Statuscode-Nachricht entspricht. Beachten Sie, dass HTTP/2 does not support -Statusmeldungen angezeigt werden.
  • Response.ok – wie oben gezeigt, ist dies eine Abkürzung für die Überprüfung, ob der Status im Bereich von 200 bis einschließlich 299 liegt. Dies gibt einen boolean -Wert zurück.

Sie können auch programmgesteuert über JavaScript erstellt werden, aber das ist nur in ServiceWorkers wirklich nützlich, wenn Sie eine benutzerdefinierte Antwort auf eine empfangene Anfrage mithilfe einer respondWith() -Methode bereitstellen:

js

const myBody = new Blob();addEventListener("fetch", (event) => { // ServiceWorker fängt einen Abruf ab event.respondWith( new Response(myBody, { headers: { "Content-Type": "text/plain" }, }), );});

Der Response() -Konstruktor akzeptiert zwei optionale Argumente – einen Hauptteil für die Antwort und ein Init-Objekt (ähnlich dem, das Request() akzeptiert).

Hinweis: Die static -Methode error() gibt eine Fehlerantwort zurück. Ebenso gibt redirect() eine Antwort zurück, die zu einer Weiterleitung zu einer angegebenen URL führt. Auch diese sind nur für Servicemitarbeiter relevant.

Body

Sowohl Anfragen als auch Antworten können Körperdaten enthalten. Ein Körper ist eine Instanz eines der folgenden Typen:

Die Schnittstellen Request und Response teilen sich die folgenden Methoden zum Extrahieren eines Körpers. Diese geben alle einen promise zurück, der schließlich mit dem tatsächlichen Inhalt aufgelöst wird.

  • Request.arrayBuffer() / Response.arrayBuffer()
  • Request.blob() / Response.blob()
  • Request.formData() / Response.formData()
  • Request.json() / Response.json()
  • Request.text() / Response.text()

Dies macht die Nutzung nicht-textueller Daten viel einfacher als mit XHR.

Anforderungstexte können durch Übergabe von Textparametern festgelegt werden:

js

const form = new FormData(document.getElementById("login-form"));fetch("/login", { method: "POST", body: form,});

Sowohl die Anfrage als auch die Antwort (und damit auch die fetch() -Funktion) versuchen, den Inhaltstyp intelligent zu bestimmen. Eine Anfrage setzt außerdem automatisch einen Content-Type -Header, wenn none im Parameter options festgelegt ist.

Feature detection

Die Unterstützung der Fetch-API kann erkannt werden, indem überprüft wird, ob Headers , Request , Response oder fetch() im Bereich Window oder Worker vorhanden sind. Zum Beispiel:

js

if (window.fetch) { // run my fetch request here} else { // do something with XMLHttpRequest?}

Unterschiede zu jQuery.ajax()

Die fetch -Spezifikation unterscheidet sich in folgenden wesentlichen Punkten von der jQuery.ajax() -Spezifikation:

  • Der von fetch() zurückgegebene promise wird bei HTTP-Fehlern nicht abgelehnt, selbst wenn die Antwort ein HTTP 404 oder 500 ist. Stattdessen wird der promise aufgelöst, sobald der Server mit Headern antwortet (wobei die ok -Eigenschaft der Antwort auf false gesetzt ist, wenn). die Antwort liegt nicht im Bereich 200–299). Der promise lehnt die Anfrage nur ab, wenn ein Netzwerkfehler vorliegt oder wenn irgendetwas den Abschluss der Anfrage verhindert.
  • Sofern fetch() nicht mit der Option credentials aufgerufen wird, die auf include , fetch() gesetzt ist:
    • sendet keine Cookies in Cross-Origin-Anfragen
    • Setzt keine Cookies, die in Cross-Origin-Antworten zurückgesendet werden
    • Ab August 2018 wurde die Standardanmeldeinformationsrichtlinie auf „Same-Origin“ geändert.

See also

© 2005–2023 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

Web APIs - Fetch-API: Verwenden von Fetch (2024)

References

Top Articles
Latest Posts
Article information

Author: Ray Christiansen

Last Updated:

Views: 5552

Rating: 4.9 / 5 (49 voted)

Reviews: 88% of readers found this page helpful

Author information

Name: Ray Christiansen

Birthday: 1998-05-04

Address: Apt. 814 34339 Sauer Islands, Hirtheville, GA 02446-8771

Phone: +337636892828

Job: Lead Hospitality Designer

Hobby: Urban exploration, Tai chi, Lockpicking, Fashion, Gunsmithing, Pottery, Geocaching

Introduction: My name is Ray Christiansen, I am a fair, good, cute, gentle, vast, glamorous, excited person who loves writing and wants to share my knowledge and understanding with you.