Laufzeitfehler brechen die Ausführung ab, solange sie niemand abfängt. Mit try, catch und finally fängst du sie gezielt ab. Mit throw meldest du selbst Fehler. Das brauchst du überall, wo Eingaben, Netzwerk oder Parsing schiefgehen können.
try, catch und finally
Der catch-Block läuft nur, wenn im try-Block ein Fehler auftritt. finally läuft immer, auch nach einem return. Seit ES2019 darfst du den Parameter weglassen (optional catch binding).
const parseConfig = (json) => {
try {
return JSON.parse(json);
} catch (err) {
console.error(`Ungültiges JSON: ${err.message}`);
return {};
} finally {
console.log('Parsing abgeschlossen');
}
};
try { riskyCall(); } catch { /* Fehler bewusst ignoriert */ }
Fehler werfen und eigene Fehlerklassen
Wirf immer Error-Objekte oder Unterklassen davon, keine Strings. Nur so bekommst du message, name und einen Stacktrace. Eingebaute Typen sind z. B. TypeError, RangeError und SyntaxError. Mit der Option cause (ES2022) hängst du den ursprünglichen Fehler an.
class ValidationError extends Error {
constructor(field, message, options) {
super(message, options);
this.name = 'ValidationError';
this.field = field;
}
}
try {
throw new ValidationError('email', 'E-Mail fehlt');
} catch (err) {
if (err instanceof ValidationError) {
console.warn(`${err.field}: ${err.message}`);
} else {
throw err; // Unbekanntes nicht verschlucken
}
}
Fehler in asynchronem Code
Bei await funktioniert try/catch wie bei synchronem Code. Aufgepasst: fetch wirft bei HTTP-Status 404 oder 500 keinen Fehler. Den Status musst du selbst prüfen.
const loadUser = async (id) => {
try {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} catch (err) {
throw new Error('Benutzer konnte nicht geladen werden', { cause: err });
}
};
loadUser(42).catch((err) => console.error(err.message, err.cause));
Best Practices
- Fang nur Fehler ab, die du auch sinnvoll behandeln kannst. Alles andere wirfst du erneut.
- Promises ohne
awaitoder.catch()führen zu unhandled rejections. - Ein
returninfinallyüberschreibt Rückgabewerte und verschluckt Fehler. Das solltest du vermeiden.