Start · Sprachen · JavaScript · Kapitel · Fehlerbehandlung & Exceptions
// Kapitel · JavaScript

Fehlerbehandlung & Exceptions

Diese Sektion zeigt, wie du in JavaScript Fehler mit try/catch/finally abfängst, mit throw eigene Exceptions auslöst und Fehler in asynchronem Code sauber behandelst.

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 await oder .catch() führen zu unhandled rejections.
  • Ein return in finally überschreibt Rückgabewerte und verschluckt Fehler. Das solltest du vermeiden.