AJAX: Ein Leitfaden für asynchrone HTTP-Anfragen in JavaScript
November 24, 2016
AJAX (Asynchronous JavaScript and XML) ist eine grundlegende Webentwicklungstechnik, die es einer Webseite ermöglicht, asynchron mit einem Server zu kommunizieren. Anstatt die gesamte Seite bei jeder Interaktion neu zu laden, können Daten im Hintergrund gesendet und empfangen werden, um die Benutzeroberfläche dynamisch zu aktualisieren.
Dieser Ansatz ist die Basis für moderne, interaktive Webanwendungen und bietet entscheidende Vorteile:
- Verbesserte User Experience (UX): Nahtlose Interaktionen ohne störende Seitenneuladungen.
- Effiziente Ressourcennutzung: Es werden nur die tatsächlich benötigten Daten übertragen.
- Echtzeit-Funktionalität: Ermöglicht die Implementierung von Live-Feeds, Chats und Benachrichtigungen.
Obwohl XML historisch namensgebend war, ist JSON heute das dominierende Format für den Datenaustausch.
Grundkonzepte des HTTP-Protokolls
- Request: Eine Anfrage vom Client an den Server, bestehend aus Methode (GET, POST, etc.), URL, Headern und einem optionalen Body.
- Response: Eine Antwort vom Server, bestehend aus einem Statuscode, Headern und einem optionalen Body (Payload).
- Asynchronität: Die Anfrage blockiert nicht den Haupt-Thread des Browsers, sodass die UI responsiv bleibt.
Wichtige HTTP-Statuscodes
200 OK: Anfrage erfolgreich.201 Created: Ressource erfolgreich erstellt.204 No Content: Anfrage erfolgreich, aber keine Daten im Body.400 Bad Request: Fehlerhafte Anfrage vom Client (z.B. ungültige Daten).401 Unauthorized/403 Forbidden: Authentifizierung oder Autorisierung fehlgeschlagen.404 Not Found: Die angeforderte Ressource existiert nicht.500 Internal Server Error: Ein allgemeiner Fehler auf dem Server.
Evolution der AJAX-Techniken
XMLHttpRequest(Legacy): Die ursprüngliche, ereignisbasierte Browser-API. Funktional, aber umständlich und veraltet.- jQuery
$.ajax()(Historisch): Eine populäre Abstraktion, die die Browser-Inkompatibilitäten von XHR vereinfachte. - Fetch API (Moderner Standard): Eine moderne, Promise-basierte Schnittstelle, die in allen aktuellen Browsern verfügbar ist.
async/await(Syntaktischer Zucker): Eine syntaktische Verbesserung für die Arbeit mit Promises, die asynchronen Code lesbarer macht.
Methode 1: XMLHttpRequest (XHR) - Historisch
XHR ist die ursprüngliche Methode zur Durchführung von AJAX-Anfragen. Die Verwendung wird für neue Projekte nicht mehr empfohlen, ist aber für das Verständnis und die Wartung von Altsystemen relevant.
GET-Anfrage
const xhr = new XMLHttpRequest();
// Konfiguriert die Anfrage
xhr.open("GET", "https://api.example.com/data");
// Definiert, was bei erfolgreichem Abschluss passiert
xhr.onload = function () {
if (xhr.status === 200) {
const data = JSON.parse(xhr.response);
console.log("Daten erhalten:", data);
} else {
console.error("Fehler:", xhr.status, xhr.statusText);
}
};
// Definiert die Fehlerbehandlung für Netzwerkprobleme
xhr.onerror = function () {
console.error("Netzwerkfehler aufgetreten.");
};
// Sendet die Anfrage
xhr.send();
POST-Anfrage mit JSON
const xhr = new XMLHttpRequest();
xhr.open("POST", "https://api.example.com/users");
// Setzt die notwendigen Header für eine JSON-Anfrage
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Authorization", "Bearer YOUR_TOKEN_HERE");
xhr.onload = function () {
if (xhr.status === 201) { // 201 Created
console.log("Benutzer erstellt:", JSON.parse(xhr.response));
}
};
const payload = { name: "John Doe", email: "john@example.com" };
xhr.send(JSON.stringify(payload));
Upload-Fortschritt
Ein Bereich, in dem XHR nützlich bleibt, ist die Verfolgung des Upload-Fortschritts, da die Fetch API dies nicht nativ unterstützt.
const xhr = new XMLHttpRequest();
xhr.upload.onprogress = function (event) {
if (event.lengthComputable) {
const percentComplete = (event.loaded / event.total) * 100;
console.log(`Upload-Fortschritt: ${percentComplete.toFixed(2)}%`);
}
};
const formData = new FormData();
formData.append("file", myFileInput.files[0]);
xhr.open("POST", "https://api.example.com/upload");
xhr.send(formData);
Methode 2: Fetch API - Moderner Standard
Die Fetch API ist die empfohlene Methode für neue Projekte. Sie ist Promise-basiert und bietet eine saubere, flexible Schnittstelle.
GET-Anfrage mit async/await (Empfohlen)
async function fetchData() {
try {
const response = await fetch("https://api.example.com/data");
// Wichtig: fetch() wirft bei HTTP-Fehlern (4xx/5xx) keinen Fehler!
if (!response.ok) {
throw new Error(`HTTP-Fehler! Status: ${response.status}`);
}
const data = await response.json();
console.log(data);
return data;
} catch (error) {
console.error("Fehler beim Abrufen der Daten:", error);
}
}
POST-Anfrage mit JSON
async function createUser(payload) {
try {
const response = await fetch("https://api.example.com/users", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_TOKEN_HERE",
},
body: JSON.stringify(payload),
});
if (!response.ok) {
throw new Error(`HTTP-Fehler! Status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error("Fehler beim Erstellen des Benutzers:", error);
}
}
Timeout mit AbortController
fetch bietet keinen nativen Timeout. Dieser kann jedoch mit einem AbortController implementiert werden.
async function fetchWithTimeout(url, timeout = 5000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, { signal: controller.signal });
return response;
} finally {
clearTimeout(timeoutId);
}
}
CORS (Cross-Origin Resource Sharing)
Aus Sicherheitsgründen erzwingen Browser die Same-Origin Policy, die verhindert, dass eine Webseite Anfragen an eine andere Domain (Origin) stellt. Um Cross-Origin-Anfragen zu ermöglichen, muss der Zielserver CORS unterstützen, indem er den Access-Control-Allow-Origin-Header in seiner Antwort sendet.
Bibliotheken und Frameworks
In React-Anwendungen werden oft spezialisierte Bibliotheken für den Datenabruf verwendet, die über fetch hinausgehen:
- Axios: Ein beliebter, Promise-basierter HTTP-Client mit Features wie Interceptors und Timeouts.
- SWR & React Query (TanStack Query): Hoch-abstrahierte Bibliotheken, die Caching, Revalidierung, und Status-Management für Datenabfragen bereitstellen.
Beispiel mit Axios:
import axios from "axios";
async function fetchDataWithAxios() {
try {
const response = await axios.get("https://api.example.com/data");
console.log(response.data);
} catch (error) {
// Axios wirft automatisch Fehler bei 4xx/5xx Statuscodes
console.error("Fehler:", error.message);
}
}
Best Practices
- Fehlerbehandlung: Implementieren Sie immer eine robuste Fehlerbehandlung, sowohl für Netzwerkprobleme als auch für HTTP-Fehlerstatus.
- Timeouts: Setzen Sie Timeouts, um zu verhindern, dass Ihre Anwendung auf langsame Serverantworten wartet.
- Sicherheit: Speichern Sie niemals API-Schlüssel oder andere sensible Daten im Frontend-Code.
- Validierung: Validieren Sie immer die vom Server empfangenen Daten, bevor Sie sie verwenden.