async/await in JavaScript
async/await in JavaScript
~14 Min. Lesezeit Zuletzt aktualisiert am 8. August 2026
async/await ist "syntaktischer Zucker" über Promises (Kapitel 24) – GENAU dieselbe Funktionalität, aber in einer Syntax, die sich wie SYNCHRONER Code liest. Wir bauen damit das endgültige Datei-Lade-System unseres Haushaltsbuchs.
Die async-Funktion
Ein async vor einer Funktion bewirkt zwei Dinge: Die Funktion gibt IMMER ein Promise zurück (auch wenn im Körper kein Promise erwähnt wird), und innerhalb der Funktion darf await verwendet werden.
import { readFile } from 'node:fs/promises'; // die Promise-basierte Variante von fs!
async function ladeTransaktionen(pfad) {
const inhalt = await readFile(pfad, 'utf-8'); // 'pausiert' HIER, bis das Promise erfüllt ist
return JSON.parse(inhalt);
}
console.log(typeof ladeTransaktionen('transaktionen.json')); // Fehler! Nicht awaited - siehe untennode:fs/promises ist eine Promise-basierte Variante des fs-Moduls (im Gegensatz zur Callback-Version aus Kapitel 24) – der Standard-Weg für Datei-Operationen in modernem async/await-Code.
await ist nur innerhalb async-Funktionen erlaubt
async function verarbeite() {
const transaktionen = await ladeTransaktionen('transaktionen.json');
console.log(`${transaktionen.length} Transaktionen geladen`);
return transaktionen;
}
verarbeite(); // gibt selbst wieder ein Promise zurück - siehe nächster Abschnittawait "pausiert" NUR die aktuelle async-Funktion – der Rest des Programms läuft weiter, GENAU wie in Kapitel 23 erklärt (das Event-Loop-Wissen von dort gilt hier unverändert, nur die Syntax hat sich geändert).
Das Ergebnis einer async-Funktion nutzen
Da ladeTransaktionen selbst ein Promise zurückgibt, gibt es zwei gültige Wege, an das Ergebnis zu kommen:
// Weg 1: .then() (aus Kapitel 24, funktioniert weiterhin identisch)
ladeTransaktionen('transaktionen.json').then(transaktionen => {
console.log(transaktionen.length);
});
// Weg 2: await, aus einer WEITEREN async-Funktion heraus
async function main() {
const transaktionen = await ladeTransaktionen('transaktionen.json');
console.log(transaktionen.length);
}
main();Mehrere await-Aufrufe: sequenziell vs. parallel
Ein häufiger Performance-Fehler: mehrere UNABHÄNGIGE await-Aufrufe nacheinander, statt sie parallel laufen zu lassen:
// Langsam - sequenziell, jeder wartet auf den vorherigen (Gesamtzeit: Summe aller drei):
async function ladeAlleLangsamer() {
const januar = await ladeTransaktionen('januar.json');
const februar = await ladeTransaktionen('februar.json');
const maerz = await ladeTransaktionen('maerz.json');
return [januar, februar, maerz];
}
// Schnell - parallel, alle drei starten gleichzeitig (Gesamtzeit: Zeit des LANGSAMSTEN):
async function ladeAlleSchneller() {
return Promise.all([
ladeTransaktionen('januar.json'),
ladeTransaktionen('februar.json'),
ladeTransaktionen('maerz.json'),
]);
}Tipp: Faustregel: Sind die await-Aufrufe VONEINANDER ABHÄNGIG (Aufruf 2 braucht das Ergebnis von Aufruf 1), MUSS sequenziell gewartet werden. Sind sie UNABHÄNGIG, ist Promise.all() mit anschließendem einzelnen await fast immer schneller.
Top-Level await
In ES Modules (Kapitel 21) darf await auch AUSSERHALB einer async-Funktion direkt auf der obersten Dateiebene stehen:
import { ladeTransaktionen } from './dateiSpeicher.js';
const transaktionen = await ladeTransaktionen('transaktionen.json'); // Top-Level await
console.log(`${transaktionen.length} Transaktionen geladen`);In Kapitel 26 ergänzen wir dieses System um saubere Fehlerbehandlung – await-Aufrufe, die fehlschlagen, werfen einen normalen JavaScript-Error, den wir mit try/catch abfangen können, statt .catch()-Ketten zu brauchen.