Fetch API HTTP Requests
Fetch API: Moderne HTTP Requests in JavaScript
Die Fetch API ist der moderne Standard für HTTP-Anfragen im Browser. Lernen Sie GET, POST und andere Methoden mit async/await.
Grundlegender GET Request
// Einfachster Fetch
fetch('https://api.example.com/users')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Fehler:', error));
// Mit async/await (empfohlen)
async function getUsers() {
try {
const response = await fetch('https://api.example.com/users');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Fehler:', error);
}
}
Response-Objekt verstehen
async function examineResponse() {
const response = await fetch('https://api.example.com/users');
// Response-Eigenschaften
console.log(response.ok); // true wenn 200-299
console.log(response.status); // 200, 404, 500, etc.
console.log(response.statusText); // "OK", "Not Found", etc.
console.log(response.headers); // Headers-Objekt
console.log(response.url); // Finale URL (nach Redirects)
console.log(response.type); // "basic", "cors", "opaque"
// Body auslesen (kann nur EINMAL gelesen werden!)
const data = await response.json(); // Als JSON
// ODER
const text = await response.text(); // Als Text
// ODER
const blob = await response.blob(); // Als Blob (Dateien)
// ODER
const buffer = await response.arrayBuffer(); // Als ArrayBuffer
}
POST Request
async function createUser(userData) {
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(userData)
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
}
// Verwendung
const newUser = await createUser({
name: 'Max Mustermann',
email: 'max@example.com'
});
Alle HTTP-Methoden
// GET - Daten abrufen
const getResponse = await fetch('/api/users/1');
// POST - Neue Ressource erstellen
const postResponse = await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Neu' })
});
// PUT - Ressource komplett ersetzen
const putResponse = await fetch('/api/users/1', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Aktualisiert', email: 'neu@mail.de' })
});
// PATCH - Ressource teilweise aktualisieren
const patchResponse = await fetch('/api/users/1', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Nur Name geändert' })
});
// DELETE - Ressource löschen
const deleteResponse = await fetch('/api/users/1', {
method: 'DELETE'
});
Headers setzen und lesen
// Headers setzen
const response = await fetch('/api/data', {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer your-token-here',
'X-Custom-Header': 'custom-value'
}
});
// Headers-Objekt verwenden
const headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Authorization', 'Bearer token');
const response2 = await fetch('/api/data', { headers });
// Response Headers lesen
const contentType = response.headers.get('Content-Type');
const cacheControl = response.headers.get('Cache-Control');
// Alle Headers durchgehen
response.headers.forEach((value, name) => {
console.log(`${name}: ${value}`);
});
Korrektes Error Handling
// ⚠️ WICHTIG: fetch wirft nur bei Netzwerkfehlern!
// HTTP 404 oder 500 sind KEINE Exceptions!
async function fetchWithErrorHandling(url) {
try {
const response = await fetch(url);
// HTTP-Fehler manuell prüfen
if (!response.ok) {
// Versuche Fehlermeldung aus Response zu lesen
let errorMessage = `HTTP ${response.status}`;
try {
const errorData = await response.json();
errorMessage = errorData.message || errorMessage;
} catch {
// Response war kein JSON
}
throw new Error(errorMessage);
}
return await response.json();
} catch (error) {
if (error.name === 'TypeError') {
// Netzwerkfehler (offline, DNS, CORS, etc.)
throw new Error('Netzwerkfehler - prüfen Sie Ihre Verbindung');
}
throw error;
}
}
Timeout implementieren
// Fetch hat KEINEN eingebauten Timeout!
// Lösung: AbortController
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
});
clearTimeout(timeoutId);
return response;
} catch (error) {
clearTimeout(timeoutId);
if (error.name === 'AbortError') {
throw new Error(`Request timeout nach ${timeout}ms`);
}
throw error;
}
}
// Verwendung
try {
const response = await fetchWithTimeout('/api/slow-endpoint', 3000);
} catch (error) {
console.log(error.message); // "Request timeout nach 3000ms"
}
Request abbrechen
// AbortController für manuelle Abbrüche
const controller = new AbortController();
// Request starten
const fetchPromise = fetch('/api/large-data', {
signal: controller.signal
});
// Abbrechen (z.B. bei User-Aktion)
document.getElementById('cancelBtn').onclick = () => {
controller.abort();
};
try {
const response = await fetchPromise;
} catch (error) {
if (error.name === 'AbortError') {
console.log('Request wurde abgebrochen');
}
}
FormData senden
// Für multipart/form-data (Datei-Uploads)
const formData = new FormData();
formData.append('name', 'Max');
formData.append('email', 'max@example.com');
formData.append('avatar', fileInput.files[0]);
const response = await fetch('/api/upload', {
method: 'POST',
body: formData // Content-Type wird automatisch gesetzt!
});
// Oder von einem Form-Element
const form = document.querySelector('form');
const formData2 = new FormData(form);
await fetch('/api/submit', {
method: 'POST',
body: formData2
});
URL-Parameter
// URLSearchParams für Query-Parameter
const params = new URLSearchParams({
page: 1,
limit: 10,
search: 'test query',
filter: 'active'
});
const url = `/api/users?${params.toString()}`;
// "/api/users?page=1&limit=10&search=test+query&filter=active"
const response = await fetch(url);
// Oder mit URL-Objekt
const url2 = new URL('https://api.example.com/users');
url2.searchParams.set('page', '1');
url2.searchParams.set('limit', '10');
await fetch(url2);
Wiederverwendbarer API-Client
// API-Wrapper Klasse
class ApiClient {
constructor(baseUrl, defaultHeaders = {}) {
this.baseUrl = baseUrl;
this.defaultHeaders = {
'Content-Type': 'application/json',
...defaultHeaders
};
}
setAuthToken(token) {
this.defaultHeaders['Authorization'] = `Bearer ${token}`;
}
async request(endpoint, options = {}) {
const url = `${this.baseUrl}${endpoint}`;
const response = await fetch(url, {
...options,
headers: {
...this.defaultHeaders,
...options.headers
}
});
if (!response.ok) {
const error = await response.json().catch(() => ({}));
throw new Error(error.message || `HTTP ${response.status}`);
}
return response.json();
}
get(endpoint) {
return this.request(endpoint);
}
post(endpoint, data) {
return this.request(endpoint, {
method: 'POST',
body: JSON.stringify(data)
});
}
put(endpoint, data) {
return this.request(endpoint, {
method: 'PUT',
body: JSON.stringify(data)
});
}
delete(endpoint) {
return this.request(endpoint, { method: 'DELETE' });
}
}
// Verwendung
const api = new ApiClient('https://api.example.com');
api.setAuthToken('my-jwt-token');
const users = await api.get('/users');
const newUser = await api.post('/users', { name: 'Max' });
💡 Tipp:
Vergessen Sie nie,
response.ok zu prüfen! Fetch wirft bei HTTP-Fehlern (404, 500) keine Exception. Nutzen Sie AbortController für Timeouts und Request-Abbrüche.