Network Requests

Fetch API & AJAX

Jede moderne Web-App kommuniziert mit einem Server. Die Fetch API ist der Standardweg, um Anfragen zu senden, Antworten zu lesen und die Seite ohne vollständigen Reload zu aktualisieren.

intermediate15 min readUpdated 15. Sept. 2026
js
// api.js
async function getUsers() {
  const res = await fetch("/api/users", {
    headers: { Accept: "application/json" },
  });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

const users = await getUsers();
console.log(users);
Standard
Teil des Fetch Living Standard
Rückgabewert
Ein Promise<Response>
Ersetzt
XMLHttpRequest
Body lesen als
json, text, blob, formData
Abbrechen mit
AbortController
Reject bei
Nur Netzwerkfehlern

Praxis

Fetch-Request ausprobieren

Diese Demo ruft eine JSON-Daten-URL auf und funktioniert daher auch offline.

Fetch-Request ausprobieren

Diese Demo ruft eine JSON-Daten-URL auf und funktioniert daher auch offline.

Warum es wichtig ist

Warum fetch wichtig ist

Eine API für alles

Der gleiche fetch-Aufruf verarbeitet JSON-APIs, Text, Dateien, Streams und Formulardaten über verschiedene Browser und Runtimes hinweg.

Promise-basiert

Fetch gibt ein Promise zurück und lässt sich daher perfekt mit async/await und Promise-Kombinatoren kombinieren.

Standardmäßig sicher

Sinnvolle Standardwerte für CORS und Credentials helfen dabei, versehentliche Datenlecks zu vermeiden.

Das Gesamtbild

Die drei Teile jeder Anfrage

Ein Netzwerk-Request besteht aus einer Anfrage, einer Antwort und der Fehlerbehandlung darum herum. Wenn diese drei Dinge stimmen, ist der Rest nur noch Detailarbeit.

Die Anfrage

Senden

URL, Methode, Header und Body beschreiben exakt, was der Server tun soll.

Die Antwort

Lesen

Status, Header und ein Body, den du als JSON, Text, Blob oder Stream parst.

Die Fehler

Wiederherstellen

Unterscheide zwischen Netzwerkfehlern und HTTP-Fehlerstatus, um dem Nutzer hilfreiche Informationen anzuzeigen.

Fetch auf einen Blick

Was die Fetch API bietet

GET-Requests

Daten von einer URL abrufen und den Response-Body lesen.

POST & PUT

Daten mit einer Methode, Headern und einem Body an den Server senden.

JSON lesen

res.json() parst den Response-Body in einen JavaScript-Wert.

Fehlerbehandlung

Prüfe res.ok für HTTP-Fehler und nutze catch für Netzwerkfehler.

Abbrechen

AbortController stoppt Anfragen, die nicht mehr benötigt werden.

CORS & Credentials

Verstehe Origins, Preflight-Requests und wann Cookies gesendet werden.

Eine kurze Geschichte

Von XMLHttpRequest zu fetch

  1. 1999

    XMLHttpRequest

    Microsoft führt XHR ein, und die AJAX-Ära beginnt.

    99
  2. 2005

    AJAX wird Mainstream

    Gmail und Google Maps beweisen, dass Seiten aktualisiert werden können, ohne neu zu laden.

    05
  3. 2015

    Die Fetch API

    Ein saubererer, Promise-basierter Ersatz für XHR erscheint in den Browsern.

    15
  4. 2017

    async / await

    Fetch wird durch die neue Syntax dramatisch besser lesbar.

    17
  5. Heute

    Der Standard

    Fetch ist die Standard-Request-API in Browsern, Node.js, Deno und Edge-Runtimes.

    Heute

Der vollständige Leitfaden

Fetch API & AJAX: Alles was Sie wissen müssen

Was ist AJAX?

AJAX steht für Asynchronous JavaScript and XML – ein Begriff, der 2005 geprägt wurde, als Gmail und Google Maps erstmals zeigten, dass eine Seite neue Daten abrufen kann, ohne komplett neu geladen werden zu müssen. Der XML-Teil gehört größtenteils der Vergangenheit an – moderne APIs liefern JSON zurück –, aber die Kernidee bleibt dieselbe: Im Hintergrund mit einem Server kommunizieren und die Seite an Ort und Stelle aktualisieren.

Das ursprüngliche Werkzeug war XMLHttpRequest. Es funktioniert zwar, aber die API ist unhandlich und basiert auf Callbacks. Der moderne Ersatz ist die Fetch API, eine Promise-basierte Schnittstelle, die in Browsern, Node.js, Deno und Edge-Runtimes verfügbar ist.

Deine erste fetch-Anfrage

fetch nimmt eine URL entgegen und gibt ein Promise für ein Response zurück.

// basic.js
const response = await fetch("https://api.example.com/users");
const users = await response.json();

console.log(users);

Das ist bereits der gesamte „Happy Path“. Die Besonderheit dabei ist, dass fetch auch bei Fehler-Statuscodes aufgelöst wird – ein 404 wirft also keinen Fehler. Du musst die Antwort also selbst prüfen.

Das Response-Objekt

Das Response-Objekt teilt Ihnen mit, was der Server zurückgesendet hat.

// response.js
const response = await fetch("/api/users");

response.ok;      // true for status 200–299
response.status;  // 200, 404, 500, ...
response.statusText;
response.headers.get("content-type");

const data = await response.json();   // parse JSON
const text = await response.text();   // raw text
const blob = await response.blob();   // binary data
const form = await response.formData();

Ein Body kann nur einmal gelesen werden. Wenn Sie sowohl den rohen Text als auch das geparste JSON benötigen, rufen Sie response.clone() vor dem Lesen auf oder parsen Sie den Text selbst. Beachten Sie außerdem, dass response.json() abgelehnt wird, wenn der Body kein gültiges JSON ist – ein weiterer Grund, Aufrufe in try/catch zu kapseln.

Fehler richtig behandeln

Es gibt zwei Arten von Fehlern, die sich unterschiedlich verhalten.

  1. Netzwerkfehler — keine Verbindung, DNS-Fehler, blockiertes CORS. fetch wird abgelehnt (rejects), daher werden sie von catch abgefangen.
  2. HTTP-Fehler — 404, 401, 500. fetch wird aufgelöst (resolves); Sie müssen response.ok oder response.status prüfen.
// errors.js
async function getUser(id) {
  try {
    const response = await fetch(`/api/users/${id}`);
    if (!response.ok) {
      throw new Error(`Request failed with status ${response.status}`);
    }
    return await response.json();
  } catch (error) {
    console.error("Could not load user:", error);
    throw error;
  }
}

Die explizite Behandlung beider Fälle ist das, was fragilen Code von resilientem Code unterscheidet. Der Leitfaden zur Fehlerbehandlung beschreibt die übergeordnete Strategie.

Daten mit POST, PUT und DELETE senden

Übergib ein Options-Objekt, um die Methode zu ändern, Header hinzuzufügen und einen Body anzuhängen.

// create.js
async function createUser(user) {
  const response = await fetch("/api/users", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json",
    },
    body: JSON.stringify(user),
  });

  if (!response.ok) throw new Error("Could not create user");
  return response.json();
}

await createUser({ name: "Ada", role: "engineer" });

Verwende PUT, um eine Ressource zu ersetzen, PATCH, um einen Teil davon zu aktualisieren, und DELETE, um sie zu entfernen. Erstelle für Datei-Uploads ein FormData-Objekt und übergib dieses als Body – der Browser setzt automatisch den korrekten Multipart-Content-Type.

Header und Authentifizierung

Header enthalten Metadaten über die Anfrage. Du kannst sie pro Request setzen, und viele APIs erwarten einen Authorization-Token.

// auth.js
const response = await fetch("/api/me", {
  headers: {
    Authorization: `Bearer ${token}`,
    Accept: "application/json",
  },
});

Hardcode niemals Secrets in clientseitigem Code – alles, was an den Browser gesendet wird, ist öffentlich. Tokens sollten aus einem Login-Flow stammen und sorgfältig gespeichert werden.

Requests abbrechen

Ein Request, der nicht mehr relevant ist – etwa weil der Nutzer ein weiteres Zeichen eingegeben hat, die Seite gewechselt hat oder die Komponente unmounted wurde –, sollte abgebrochen werden. AbortController erledigt genau das.

// abort.js
const controller = new AbortController();

fetch("/api/search?q=javascript", { signal: controller.signal })
  .then((res) => res.json())
  .then(console.log)
  .catch((error) => {
    if (error.name === "AbortError") return;
    console.error(error);
  });

// Cancel when it is no longer needed
controller.abort();

Da fetch keine Timeout-Option besitzt, ist AbortController ebenfalls der Standardweg, um einen Timeout zu implementieren.

// timeout.js
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 5000);

try {
  const res = await fetch("/api/slow", { signal: controller.signal });
  return await res.json();
} finally {
  clearTimeout(timer);
}

CORS und Credentials

Browser setzen die Same-Origin Policy durch: JavaScript kann keine Antworten von einem anderen Origin lesen, es sei denn, der Server erlaubt dies explizit. Diese Freigabe erfolgt über CORS und wird vollständig auf dem Server über Response-Header wie Access-Control-Allow-Origin konfiguriert. Wenn Sie einen CORS-Fehler sehen, muss die Lösung in der Server-Konfiguration gesucht werden, nicht in Ihrem fetch-Aufruf.

Standardmäßig sendet fetch keine Cookies an Cross-Origin-URLs. Um diese einzuschließen, setzen Sie credentials: "include" und stellen Sie sicher, dass der Server Anfragen mit Credentials zulässt. Dies ist eine häufige Ursache für die Verwirrung „In Postman funktioniert es, aber nicht im Browser“.

Praktische Patterns

Loading-, Success- und Error-States. Spiegele den Request-Lifecycle immer in der UI wider.

// state.js
async function loadPosts() {
  showSpinner();
  try {
    const res = await fetch("/api/posts");
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    renderPosts(await res.json());
  } catch (error) {
    showError("Could not load posts. Try again.");
  } finally {
    hideSpinner();
  }
}

Debounced Search. Brich den vorherigen Request ab, sobald ein neuer startet, damit langsame Antworten keine aktuellen Ergebnisse überschreiben. Kombiniere AbortController mit einer kurzen Debounce-Verzögerung.

Parallele Requests. Nutze Promise.all, wenn mehrere Endpunkte gleichzeitig benötigt werden, und Promise.allSettled, wenn ein teilweises Ergebnis bereits nützlich ist.

Best Practices

  • Überprüfe immer response.ok, bevor du den Body parst.
  • Setze einen expliziten Accept-Header und ein Content-Type, wenn du einen Body sendest.
  • Kapsle await-Requests in try/catch und gib eine hilfreiche Fehlermeldung aus.
  • Brich veraltete Requests mit AbortController ab.
  • Bündle API-Aufrufe in einem kleinen Modul, anstatt URLs über die Komponenten zu verteilen.
  • Schreibe niemals Secrets in den clientseitigen Code.
  • Zeige Lade- und Fehlerzustände an, damit sich die UI niemals “kaputt” anfühlt.

Häufige Fehler

  • Die Annahme, dass fetch bei einem 404- oder 500-Fehler eine Exception wirft.
  • Das Vergessen von JSON.stringify im Request-Body.
  • Ein fehlender Content-Type-Header, was zu einem Parse-Error vom Server führt.
  • Das mehrfache Auslesen eines Response-Bodys.
  • CORS zu ignorieren, bis der Browser die Anfrage in der Production-Umgebung blockiert.
  • Requests nicht zu canceln, wodurch veraltete Daten einen Race Condition gewinnen.

Wie geht es weiter?

Fetch ist die Brücke zwischen deinem Front End und der Außenwelt. Kombiniere es mit dem DOM, um Ergebnisse zu rendern, async/await, um Abläufe zu steuern, und error handling, um Fehler elegant abzufangen. Vertiefe von dort aus dein Wissen über Methoden, Status-Codes und Header, da diese jede Anfrage, die du sendest, maßgeblich bestimmen.

Antwort prüfen

fetch rejectet nur bei Netzwerkfehlern. Ein 404 oder 500 wird trotzdem resolved, daher prüfe res.ok.

Bevorzugt
const res = await fetch("/api/data");
if (!res.ok) {
  throw new Error(`HTTP ${res.status}`);
}
const data = await res.json();
Vermeiden
const res = await fetch("/api/data");
const data = await res.json();
// silently parses error pages

JSON senden

Teile dem Server mit, was du sendest, und wandle den Body in einen String um.

Bevorzugt
await fetch("/api/users", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ name: "Ada" }),
});
Vermeiden
await fetch("/api/users", {
  method: "POST",
  body: { name: "Ada" },
});

Häufig gestellte Fragen

Häufig gestellte Fragen

Keep learning

Related topics from the roadmap.

$ Lernen Sie jetzt

Bereit, Fetch API & AJAX zu lernen?

Unser interaktives Tutorial führt Sie Schritt für Schritt durch Fetch API & AJAX — mit Quizzen und echtem Code, den Sie im Browser ausführen können.