mitmario.dev

try, catch, finally

JavaScript Im Browser 4 Min Lesezeit 3 BeispieleLektion 2 von 6

Bis hierhin hat ein Fehler immer dasselbe getan: Er hat das Programm angehalten. Alles ab der betroffenen Zeile passiert nicht mehr.

Meistens ist das genau richtig. Wenn dein Code einen Denkfehler hat, willst du das laut merken und nicht leise weitermachen. Es gibt aber Stellen, an denen ein Fehler zum normalen Betrieb gehört: Ein Server antwortet nicht, eine Datei ist kaputt, jemand tippt Unsinn in ein Feld. Dort willst du weiterarbeiten können.

Dafür gibt es try und catch.

Die Grundform

Mit und ohne Netz
const kaputt = "{ name: Mario }";

try {
  const daten = JSON.parse(kaputt);
  console.log("Gelesen:", daten);
} catch (fehler) {
  console.error("Gefangen:", fehler.message);
}

console.log("Das Programm läuft weiter.");

// Und jetzt ohne Netz. Ab hier passiert nichts mehr.
const nochmal = JSON.parse(kaputt);
console.log("Diese Zeile wird nie erreicht.");

JSON.parse ist hier nur das Beispiel für eine Funktion, die werfen kann: Sie macht aus einem Text ein Objekt, und wenn der Text nicht das erwartete Format hat, bricht sie ab. Was JSON ist und wie das Format aussieht, erklärt Lektion 16.1; für diese Lektion reicht, dass { name: Mario } kein gültiges JSON ist.

try umschließt, was schiefgehen kann. Geht alles gut, merkst du von catch nichts. Geht es schief, springt die Ausführung sofort in den catch-Block, und zwar mitten aus dem try heraus: Was danach im try stand, wird übersprungen.

Im Beispiel steht dieselbe kaputte Zeichenkette zweimal. Beim ersten Mal fängst du den Fehler ab, siehst eine ordentliche Meldung, und das Programm läuft weiter. Beim zweiten Mal ohne try ist Schluss, und die letzte Zeile wird nie erreicht.

Beachte den Unterschied in der Console: Der gefangene Fehler steht dort, weil du ihn hingeschrieben hast. Der ungefangene steht dort, weil der Browser ihn meldet, und darunter steht kein Programm mehr.

Was im catch ankommt

Was im catch ankommt
try {
  const liste = null;
  liste.push(1);
} catch (fehler) {
  console.log("name:", fehler.name);
  console.log("message:", fehler.message);
  console.log("Die ersten Zeilen des stack:");
  console.log(fehler.stack.split("\n").slice(0, 2).join("\n"));

  // Und das ganze Objekt in einer Zeile.
  console.error(fehler);
}

In den Klammern hinter catch steht ein Name für den Wert, der geworfen wurde. Bei allem, was der Browser selbst wirft, ist das ein Error-Objekt mit drei nützlichen Eigenschaften:

  • name ist die Art, also genau das aus der letzten Lektion: TypeError, ReferenceError und so weiter.
  • message ist der Text ohne die Art davor.
  • stack ist die Aufrufliste als eine einzige lange Zeichenkette.

Für eine Ausgabe an dich selbst reicht fehler.message fast immer. Für eine Ausgabe an Nutzer taugt sie meistens nicht: „Cannot read properties of null” hilft niemandem, der nur ein Formular abschicken wollte.

Den Namen fehler darfst du frei wählen. In fremdem Code heißt er oft e oder err. Wenn du ihn gar nicht brauchst, darfst du die Klammern seit ein paar Jahren auch weglassen und einfach catch { schreiben.

finally

finally läuft immer
let laeuft = false;

function verarbeiten(text) {
  laeuft = true;
  console.log("Start, laeuft ist", laeuft);
  try {
    return JSON.parse(text);
  } catch (fehler) {
    console.warn("Ging nicht:", fehler.message);
    return null;
  } finally {
    laeuft = false;
    console.log("Aufgeräumt, laeuft ist", laeuft);
  }
}

console.log("Ergebnis 1:", verarbeiten('{"name":"Mario"}'));
console.log("Ergebnis 2:", verarbeiten("kaputt"));

Nach catch darf noch ein finally stehen. Dieser Block läuft in jedem Fall: nach einem erfolgreichen try, nach einem gefangenen Fehler, und sogar dann, wenn im try ein return steht.

Das klingt nach einer Kleinigkeit und ist es nicht. finally ist der Ort zum Aufräumen.

Der typische Fall ist der gesperrte Absendeknopf aus Lektion 13.5: Du sperrst ihn, bevor die Arbeit losgeht, und gibst ihn hinterher wieder frei. Wenn die Freigabe am Ende des try steht, bleibt der Knopf bei einem Fehler für immer gesperrt. Steht sie im finally, passiert das nicht.

Im Beispiel siehst du das an einer Variablen: laeuft steht am Anfang auf true, und nach beiden Durchläufen wieder auf false, obwohl der zweite schiefgegangen ist.

Wo try/catch hingehört, und wo nicht

Die Versuchung ist groß, nach dieser Lektion alles einzupacken. Tu es nicht.

try/catch gehört um das, was außerhalb deiner Kontrolle liegt. Also um Netzwerkaufrufe, um JSON.parse mit fremden Daten, um alles, was von außen kommt. Dort ist ein Fehler kein Programmierfehler, sondern ein Betriebszustand.

Es gehört nicht um deinen eigenen Code. Wenn berechnePreis() wirft, hast du einen Fehler gemacht, und den willst du sehen und beheben. Ein catch drumherum macht ihn unsichtbar und lässt das Programm mit falschen Zahlen weiterlaufen.

Die schlimmste Form davon ist das leere catch:

Ein catch, in dem nichts steht, sagt: Mir egal, was passiert ist. Der Fehler ist weg, die Ursache nicht, und beim nächsten Mal suchst du an einer Stelle, an der gar nichts kaputt ist. Wenn du wirklich nichts tun willst, schreib wenigstens console.warn hinein und eine Zeile Kommentar, warum das hier in Ordnung ist.

Was try/catch nicht fängt

Eine Sache noch, und die kommt in Abschnitt 15 in voller Länge zurück.

try/catch fängt nur, was während des try-Blocks passiert. Wenn du darin einen Timer startest oder einen Klick-Handler hinterlegst, ist der try-Block längst vorbei, wenn der Code darin läuft. Ein Fehler dort geht am catch vorbei, als wäre es nicht da.

Das ist einer der Gründe, warum es Promises gibt. Aber der Reihe nach.

Zum Mitnehmen

try/catch gehört um das, was außerhalb deiner Kontrolle liegt: fremde Daten, fremde Dienste, JSON.parse. Nicht um jeden Block, in dem irgendwas schiefgehen könnte.

Jetzt du

Basis Konto, kostenlos

Zu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.

Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.

Was in dieser Lektion steckt

  • Artikel mit 3 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe im Editor, direkt im Browser geprüft

    Öffnet sich mit dem Basis Konto.