Die Fetch API in JavaScript: HTTP-Requests im Browser meistern

Wie du mit der Fetch API Daten von Servern lädst und sendest – von GET und POST über Fehlerbehandlung bis zu async/await und dem AbortController.

Teilen

Fast jede moderne Web-App muss Daten von einem Server holen oder dorthin schicken: Beiträge laden, ein Formular absenden, eine Suche abschicken. Früher war dafür das umständliche XMLHttpRequest-Objekt nötig. Heute erledigst du das mit der Fetch API – einer eingebauten, promise-basierten Schnittstelle, die in jedem aktuellen Browser verfügbar ist. In diesem Beitrag lernst du, wie du mit fetch() sauber HTTP-Requests machst, Fehler richtig behandelst und typische Stolperfallen vermeidest.

Der einfachste Fall: ein GET-Request

Die Funktion fetch() nimmt eine URL entgegen und gibt ein Promise zurück, das mit einem Response-Objekt erfüllt wird. Weil die Antwort erst nach und nach eintrifft, musst du den Body in einem zweiten Schritt auslesen – zum Beispiel als JSON mit response.json(), was ebenfalls ein Promise zurückgibt.

fetch("https://api.example.com/users")
  .then((response) => response.json())
  .then((data) => {
    console.log("Erhaltene Nutzer:", data);
  })
  .catch((error) => {
    console.error("Etwas ist schiefgelaufen:", error);
  });

Die Kette liest sich fast wie Prosa: hole die Daten, wandle die Antwort in JSON um, arbeite damit. Falls du mit Promises noch nicht ganz vertraut bist, hilft dir das Verständnis des Event Loops – die einzelnen Schritte laufen asynchron ab, ohne den Rest deiner Seite zu blockieren.

Lesbarer mit async/await

Verschachtelte .then()-Aufrufe werden schnell unübersichtlich. Mit async und await schreibst du denselben Ablauf so, als wäre er synchron. Das macht den Code deutlich leichter zu lesen und Fehler lassen sich mit einem vertrauten try...catch abfangen.

async function ladeNutzer() {
  try {
    const response = await fetch("https://api.example.com/users");
    const data = await response.json();
    return data;
  } catch (error) {
    console.error("Fehler beim Laden:", error);
  }
}

ladeNutzer().then((nutzer) => console.log(nutzer));

Beide Varianten sind gleichwertig – await ist letztlich nur eine bequemere Schreibweise für den Umgang mit Promises. In neuem Code ist async/await meist die bessere Wahl.

Die häufigste Stolperfalle: Fehler werden nicht automatisch geworfen

Ein Punkt, der viele überrascht: fetch() betrachtet einen Request auch dann als erfolgreich, wenn der Server mit 404 oder 500 antwortet. Das Promise wird nur bei einem echten Netzwerkfehler abgelehnt – etwa wenn gar keine Verbindung zustande kommt. Ob die Antwort inhaltlich in Ordnung ist, musst du selbst prüfen, üblicherweise über die Eigenschaft response.ok.

async function ladeDaten(url) {
  const response = await fetch(url);

  if (!response.ok) {
    throw new Error(`HTTP-Fehler: Status ${response.status}`);
  }

  return response.json();
}

Merke dir: response.ok ist genau dann true, wenn der Status im Bereich 200–299 liegt. Ohne diese Prüfung landen fehlerhafte Antworten unbemerkt in deiner Anwendung.

Daten senden mit POST

Um Daten an den Server zu schicken, übergibst du fetch() ein zweites Argument – ein Konfigurationsobjekt. Wichtig sind dabei drei Dinge: die method, der passende Content-Type im headers-Objekt und der body. JavaScript-Objekte musst du vorher mit JSON.stringify() in einen String umwandeln.

async function erstelleNutzer(nutzer) {
  const response = await fetch("https://api.example.com/users", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(nutzer),
  });

  if (!response.ok) {
    throw new Error(`Anlegen fehlgeschlagen: ${response.status}`);
  }

  return response.json();
}

erstelleNutzer({ name: "Mara", rolle: "Entwicklerin" })
  .then((ergebnis) => console.log("Angelegt:", ergebnis));

Nach demselben Muster funktionieren auch PUT zum Aktualisieren und DELETE zum Löschen – du tauschst einfach den Wert von method aus. Damit deckst du bereits die vollständigen CRUD-Operationen einer REST-API ab.

Requests abbrechen mit dem AbortController

Manchmal willst du einen laufenden Request stoppen – etwa wenn ein Nutzer wegnavigiert oder bei einer Live-Suche eine neue Anfrage die alte überflüssig macht. Dafür gibt es den AbortController. Du übergibst sein signal an fetch() und rufst bei Bedarf abort() auf.

const controller = new AbortController();

// Request nach 5 Sekunden automatisch abbrechen
const timeout = setTimeout(() => controller.abort(), 5000);

try {
  const response = await fetch("https://api.example.com/langsam", {
    signal: controller.signal,
  });
  const data = await response.json();
  clearTimeout(timeout);
  console.log(data);
} catch (error) {
  if (error.name === "AbortError") {
    console.log("Request wurde abgebrochen.");
  } else {
    console.error("Anderer Fehler:", error);
  }
}

So baust du dir ein einfaches Timeout und vermeidest, dass veraltete Antworten deine Oberfläche durcheinanderbringen.

Fazit

Die Fetch API ist das Standardwerkzeug für HTTP-Requests im Browser: promise-basiert, gut lesbar in Kombination mit async/await und ohne externe Bibliotheken nutzbar. Die wichtigsten Punkte, die du dir merken solltest: Der Body wird in einem zweiten Schritt ausgelesen (etwa mit response.json()), Fehlerstatus musst du selbst über response.ok prüfen, und mit dem AbortController hast du laufende Requests unter Kontrolle. Wenn du diese Bausteine beherrschst, kannst du jede REST-API sauber anbinden. Am besten öffnest du gleich die Konsole deines Browsers und probierst einen ersten fetch()-Aufruf an einer öffentlichen Test-API aus – learning by doing bringt dich hier am schnellsten weiter.