JavaScript Promises & Async/Await

6 Kernkonzepte
Die wichtigsten Konzepte für asynchrone Programmierung in JavaScript: Promise · then() / catch() · async / await · Promise.all() · Promise.race() · Fehlerbehandlung Asynchrone Programmierung ist in JavaScript allgegenwärtig – für API-Aufrufe, Dateioperationen, Timer und mehr. Promises und async/await sind der moderne Standard für sauberen, lesbaren Code.

Promise – Asynchrone Operationen

new Promise((resolve, reject) => { ... })
new Promise((resolve, reject) => { // Asynchrone Operation resolve(wert) // oder reject(fehler) })

Promises sind Objekte, die das Ergebnis einer asynchronen Operation repräsentieren – entweder erfüllt (resolved) oder abgelehnt (rejected). Sie haben drei Zustände: pending, fulfilled, rejected.

Promise-Zustände

Zustand Beschreibung
pending Wird noch ausgeführt (initial)
fulfilled Erfolgreich abgeschlossen (resolve aufgerufen)
rejected Fehlgeschlagen (reject aufgerufen oder Fehler)
Beispiele
// Einfaches Promise
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Erfolg!");
}, 1000);
});
// Promise mit Fehler
const fehlerPromise = new Promise((resolve, reject) => {
reject(new Error("Etwas ist schiefgelaufen"));
});
// Promise.resolve() – sofort erfüllt
Promise.resolve(42);
// Promise.reject() – sofort abgelehnt
Promise.reject(new Error("Fehler"));
Tipp: Ein Promise wird sofort ausgeführt (eager). Die then()- und catch()-Methoden registrieren nur die Callbacks für den Fall, dass das Promise erfüllt oder abgelehnt wird.

then / catch / finally – Ergebnisse verarbeiten

promise.then(onFulfilled).catch(onRejected).finally(onFinally)
promise.then(ergebnis => { console.log(ergebnis) }) .catch(fehler => { console.error(fehler) }) .finally(() => { console.log("Immer ausgeführt") })

then() wird aufgerufen, wenn das Promise erfüllt wird. catch() fängt Fehler ab. finally() wird immer ausgeführt – unabhängig von Erfolg oder Fehler.

Chaining (Verkettung)

Methode Beschreibung
then(callback) Wird bei Erfolg ausgeführt (kann Promise zurückgeben)
catch(callback) Wird bei Fehler ausgeführt
finally(callback) Wird immer ausgeführt (keine Argumente)
then().then() Verkettung (jedes then kann ein Promise zurückgeben)
Beispiele
const promise = Promise.resolve(42);
promise
.then(wert => {
console.log(wert); // 42
return wert * 2;
})
.then(wert => {
console.log(wert); // 84
})
.catch(fehler => {
console.error("Fehler:", fehler);
})
.finally(() => {
console.log("Fertig");
});
42
84
Fertig
Tipp: Ein catch() am Ende der Kette fängt alle Fehler aus vorhergehenden then()-Callbacks ab. Das verhindert unbehandelte Promise-Rejections.

async / await – Saubere asynchrone Syntax

async function · await promise
async function getData() { const data = await fetchData() return data }

async/await ist syntaktischer Zucker für Promises. async deklariert eine asynchrone Funktion, die immer ein Promise zurückgibt. await pausiert die Ausführung, bis das Promise erfüllt ist.

Regeln für async/await

Regel Beschreibung
async Vor einer Funktion – macht sie asynchron
await Nur innerhalb von async-Funktionen erlaubt
try/catch Fehlerbehandlung mit try/catch (oder .catch())
Rückgabewert async-Funktionen geben immer ein Promise zurück
Beispiele
// Asynchrone Funktion mit await
async function holeDaten() {
try {
const antwort = await fetch("https://api.example.com");
const daten = await antwort.json();
return daten;
} catch (fehler) {
console.error("Fehler:", fehler);
}
}
// Aufruf der async-Funktion
holeDaten().then(daten => {
console.log(daten);
});
// Top-Level await (in ES2022 Modulen)
const ergebnis = await Promise.resolve("Hallo");
console.log(ergebnis); // "Hallo"
Tipp: Verwenden Sie try/catch mit await für eine klare Fehlerbehandlung – das ersetzt .catch() und macht den Code lesbarer.

Fehlerbehandlung – catch, try/catch, throw

try { } catch (err) { } · throw
try { const result = await asyncOperation() } catch (error) { console.error("Fehler:", error) } finally { console.log("Aufgeräumt") }

Fehlerbehandlung ist entscheidend für robuste asynchrone Anwendungen. Mit try/catch können Sie Fehler abfangen und angemessen reagieren. throw löst benutzerdefinierte Fehler aus.

Beispiele
// Fehler in async/await abfangen
async function risiko() {
try {
const data = await fetch("https://invalid.url");
return await data.json();
} catch (fehler) {
console.error("Netzwerkfehler:", fehler.message);
throw new Error("Daten konnten nicht geladen werden");
} finally {
console.log("Aufräumarbeiten...");
}
}
// Benutzerdefinierte Fehler mit throw
function pruefeZahl(n) {
if (n < 0) {
throw new Error("Zahl darf nicht negativ sein");
}
return n;
}
Tipp: Unbehandelte Promise-Fehler führen zu unhandledrejection-Events. Verwenden Sie immer .catch() oder try/catch mit await.

Promise.all / Promise.race – Mehrere Promises

Promise.all([p1, p2]) · Promise.race([p1, p2])
const ergebnisse = await Promise.all([ fetch('/api/1'), fetch('/api/2'), fetch('/api/3') ])

Promise.all() wartet auf alle Promises – wenn eines fehlschlägt, schlägt das gesamte Promise fehl. Promise.race() gibt das Ergebnis des ersten erfüllten oder abgelehnten Promises zurück.

Vergleich

Methode Beschreibung Verhalten bei Fehler
Promise.all([p1, p2]) Wartet auf alle Promises (parallel) Schlägt sofort fehl bei einem Fehler
Promise.allSettled([p1, p2]) Wartet auf alle Promises (parallel) Wartet immer auf alle (kein sofortiger Abbruch)
Promise.race([p1, p2]) Gibt das schnellste Promise zurück Gibt das schnellste (erfüllt oder abgelehnt)
Promise.any([p1, p2]) Gibt das erste erfüllte Promise Ignoriert Fehler bis alle fehlschlagen
Beispiele
// Promise.all – alle parallel ausführen
const ergebnisse = await Promise.all([
fetch("/api/1").then(res => res.json()),
fetch("/api/2").then(res => res.json()),
fetch("/api/3").then(res => res.json())
]);
// Promise.race – Timeout implementieren
const daten = await Promise.race([
fetch("/api/daten"),
new Promise((_, reject) => setTimeout(() => reject(new Error("Timeout")), 5000))
]);
// Promise.allSettled – alle Ergebnisse sammeln
const status = await Promise.allSettled([
Promise.resolve("OK"),
Promise.reject(new Error("Fehler"))
]);
Ausgabe von allSettled:
[
{ status: 'fulfilled', value: 'OK' },
{ status: 'rejected', reason: Error: Fehler }
]
Tipp: Promise.allSettled() ist ideal, wenn Sie alle Ergebnisse benötigen – auch wenn einzelne Promises fehlschlagen. Promise.race() eignet sich für Timeout-Implementierungen.

Praxistipps – Best Practices

async/await · Fehler · Performance
// Parallel statt sequentiell const [a, b] = await Promise.all([fetchA(), fetchB()]) // Fehler immer behandeln try { await riskyOp() } catch (err) { handle(err) }

Best Practices für asynchrone Programmierung – von Performance-Optimierung bis zu sauberer Fehlerbehandlung.

Beispiele
// ✅ Parallel ausführen (schneller)
const [user, posts] = await Promise.all([
fetchUser(1),
fetchPosts(1)
]);
// ❌ Sequentiell (langsam)
const user = await fetchUser(1);
const posts = await fetchPosts(1);
// ✅ IIFE (sofort ausgeführte async-Funktion)
(async () => {
try {
const daten = await fetchData();
console.log(daten);
} catch (err) {
console.error(err);
}
})();
// ✅ AbortController für Timeout und Abbruch
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 5000);
try {
const res = await fetch("/api", { signal: controller.signal });
console.log(await res.json());
} catch (err) {
if (err.name === "AbortError") {
console.log("Anfrage abgebrochen");
}
} finally {
clearTimeout(timeout);
}
Wichtig: Vergessen Sie nie die Fehlerbehandlung! Unbehandelte Promise-Rejections können zu schwer zu findenden Bugs führen. Verwenden Sie try/catch mit await oder .catch().

Asynchrone Konzepte im Überblick

Promise Zukünftiges Ergebnis
pending → fulfilled/rejected
then/catch Ergebnisse verarbeiten
.then() .catch() .finally()
async/await Syntaktischer Zucker
Lesbarer als .then()
try/catch Fehler abfangen
try { await } catch (err)
Promise.all Alle parallel
Schneller als sequenziell
Promise.race Schnellstes Ergebnis
Für Timeout

Quick Summary

Promise
Asynchrone Operation
then()
Erfolg behandeln
async
Async-Funktion
await
Auf Promise warten
Promise.all
Alle parallel
catch
Fehler abfangen
await fetch('/api') · Promise.all([p1, p2]) · try { await op() } catch (err) { }