HOWTO · JavaScript
Try ohne Catch in JavaScript
Im heutigen Beitrag lernen wir try-Anweisungen kennen, ohne catch in JavaScript zu implementieren.
Auf dieser Seite
Ja — eine JavaScript-try-Anweisung kann catch weglassen, solange eine finally-Klausel vorhanden ist. Dieses Tutorial erklärt, wann try ohne catch gültig ist, was mit einem geworfenen Fehler passiert und wann diese Form das richtige Werkzeug ist.
So funktioniert try ohne catch in JavaScript
Die JavaScript-try-Anweisung umschließt Code, der einen Fehler auslösen kann, und ist überall dort gültig, wo eine Anweisung erlaubt ist: auf der obersten Ebene eines Skripts, innerhalb einer Funktion oder verschachtelt in einem anderen try. Was sie nicht kann, ist allein zu stehen — auf einen try-Block muss eine catch-Klausel, eine finally-Klausel oder beides folgen; ein nacktes try ohne beides ist ein Syntaxfehler. Die geschweiften Klammern {} sind immer erforderlich, auch für eine einzelne Anweisung.
Syntax:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
try {
// try_statements: code that may throw
} catch (exception_var) {
// catch_statements: handle the thrown value
} finally {
// finally_statements: always run afterward
}
try_statementssind die auszuführenden Anweisungen.catch_statementssind die Anweisungen, die ausgeführt werden, wenn imtry-Block ein Wert geworfen wird.exception_varist eine optionale Kennung, die den geworfenen Wert für den zugehörigencatch-Block enthält.finally_statementswerden nach Abschluss dertry-Anweisung ausgeführt, unabhängig davon, ob ein Wert geworfen oder abgefangen wurde.
Da catch nur dann optional ist, wenn finally vorhanden ist (und umgekehrt), erlaubt die Grammatik genau drei Kombinationen:
try...catchtry...finallytry...catch...finally
Wenn ein catch-Block vorhanden ist und eine Anweisung im try-Block (oder eine von ihr aufgerufene Funktion) wirft, wechselt die Steuerung sofort zu catch; wenn nichts geworfen wird, wird catch vollständig übersprungen. Der finally-Block läuft immer, nachdem die try- und catch-Blöcke abgeschlossen sind — unabhängig davon, ob ein Wert geworfen wurde und ob catch ihn behandelt hat.
Ohne catch-Klausel läuft finally trotzdem zuerst, und danach propagiert der geworfene Wert weiter zum Aufrufer. Das gilt auch für Verschachtelungen: try-Anweisungen können verschachtelt werden, und wenn eine innere try-Anweisung kein catch hat, behandelt stattdessen der catch-Block einer umschließenden try-Anweisung den Fehler.
Die vollständige Grammatik finden Sie in der MDN-Dokumentation zu try...catch.
Beispiel: try...finally ohne catch
Das folgende Snippet platziert ein try...finally ohne eigenes catch innerhalb eines äußeren try...catch, sodass wir beobachten können, wie der finally-Block läuft und wo der geworfene Wert landet. 0 / 0 ergibt NaN, sodass throw new Error(0 / 0) ein Error-Objekt wirft, dessen Meldung NaN ist. Die Texte im Code und in der Ausgabe bleiben unverändert auf Englisch.
Führen Sie dieses Beispiel aus:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
try {
try {
console.log('Executing try block')
throw new Error(0 / 0)
} finally {
console.log('Final Call')
}
} catch (error) {
console.log('Outer catch received: ' + error.message)
}
Executing try block
Final Call
Outer catch received: NaN
Das innere try gibt seine Log-Zeile Executing try block aus und wirft dann. Da es kein catch hat, wechselt die Steuerung direkt zu finally, das Final Call ausgibt. Erst nachdem finally abgeschlossen ist, propagiert der Error weiter; dort empfängt ihn der äußere catch und gibt seine NaN-Meldung aus. Ohne dieses umschließende catch würde derselbe Fehler den Aufrufer erreichen oder — auf oberster Ebene — nach der Ausgabe von Final Call als unbehandelter Fehler auftreten.
Wann man try ohne catch verwendet
Greifen Sie zu try...finally, wenn ein Block garantierte Aufräumarbeiten braucht, der Fehler selbst aber dem Aufrufer gehört. Typische finally-Aufgaben sind das Freigeben einer Ressource, das Schließen einer Verbindung oder eines Datei-Handles, das Wiederherstellen gemeinsamen Zustands — etwa eines erneut aktivierten Buttons oder eines zurückgesetzten Flags — und das Stoppen eines Timers: Arbeiten, die erfolgen müssen, ob der try-Block nun normal endet oder wirft.
Diese Form ist die richtige Wahl, wenn der Code dem Fehler nichts Sinnvolles hinzuzufügen hat: Ein unverändertes erneutes Werfen erzeugt nur Rauschen, während ein leerer catch-Block jeden Fehler stillschweigend verschluckt, sodass Bugs weit entfernt von ihrer Ursache auftauchen. try...finally bewahrt die Aufräumgarantie und lässt den Aufrufer den Fehler trotzdem sehen und behandeln. Wenn die Funktion den geworfenen Wert wirklich untersuchen, protokollieren oder daraus wiederherstellen muss, fügen Sie stattdessen eine echte catch-Klausel hinzu.
Einschränkungen und Fallstricke von try ohne catch
finallybehandelt oder unterdrückt den Fehler niemals. Nachdemfinallyabgeschlossen ist, propagiert ein unbehandelter geworfener Wert weiter zum Aufrufer; auf oberster Ebene beendet er das Skript oder meldet einen unbehandelten Fehler.- Sie können den geworfenen Wert nicht beobachten. Ohne
catchhat das Konstrukt keinen Zugriff auf das Geworfene und kann daher weder die Meldung protokollieren noch je nach Fehlertyp verzweigen. - Die Kontrollflusssteuerung innerhalb von
finallyüberschreibt alles, was noch ausstand. Einreturnoderthrowinfinallyverwirft einen noch propagierenden Wert — einschließlich eines geworfenen Fehlers, der dann still verschwindet —; beschränken Siefinallydaher auf einfache Aufräumarbeiten, die weder zurückgeben noch werfen. - Anweisungen nach einem
try...finallylaufen nur, wenn nichts geworfen wurde, undfinallyselbst darf nicht davon abhängen, dass dertry-Block erfolgreich war, da es auch auf dem Fehlerpfad läuft.