Читать книгу JavaScript – Das Handbuch für die Praxis - David Flanagan - Страница 143

5.5.7try/catch/finally

Оглавление

Die try/catch/finally-Anweisung ist JavaScripts Mechanismus zur Ausnahmebehandlung. Die try-Klausel dieser Anweisung definiert und umschließt schlicht einen Codeblock, dessen Ausnahmen behandelt werden sollen. Auf den try-Block folgt eine catch-Klausel, die einen Block mit Anweisungen enthält, die ausgeführt werden, wenn im try-Block Ausnahmen auftreten. Auf die catch-Klausel folgt ein abschließender finally-Block mit Aufräumcode, der garantiert ausgeführt wird – ganz gleich, was im try-Block passiert. Entweder der catch- oder der finally-Block darf weggelassen werden, aber ein try-Block muss immer von mindestens einem dieser Blöcke begleitet werden. Die Blöcke try, catch und finally beginnen und enden mit geschweiften Klammern. Diese Klammern sind ein zwingender Aspekt der Syntax und dürfen nicht weggelassen werden, selbst wenn ein Block nur eine einzige Anweisung enthält.

Der folgende Code veranschaulicht diese Syntax und den Zweck der try/catch/finally-Anweisung:

try {

// Normalerweise läuft der Code dieses Blocks von Anfang bis Ende

// ohne Probleme. Aber manchmal kann eine Ausnahme ausgelöst werden,

// entweder direkt durch eine throw-Anweisung oder indirekt durch

// den Aufruf einer Methode, in der eine Ausnahme auftritt.

}

catch(e) {

// Die Anweisungen in diesem Block werden ausgeführt, wenn - und nur wenn -

// der try-Block eine Ausnahme auslöst. Diese Anweisungen können die lokale

// Variable e benutzen, um auf das Error-Objekt oder einen anderen mit der

// Ausnahme übergebenen Wert zu verweisen. Dieser Block kann die Ausnahme

// in irgendeiner Form behandeln, kann sie ignorieren oder sie durch eine

// throw-Anweisung erneut auslösen.

}

finally {

// Dieser Block enthält Anweisungen, die immer ausgeführt werden, unabhängig

// davon, was im try-Block geschieht. Sie werden ausgeführt, wenn der try-

// Block auf folgende Weisen beendet oder verlassen wird:

// 1) normal, nach Erreichen des Blockendes

// 2) wegen einer break-, continue- oder return-Anweisung

// 3) wegen einer Ausnahme, die durch die vorhergehende catch-Klausel

// behandelt wird

// 4) mit einer nicht abgefangenen Ausnahme (die sich weiterhin verbreitet)

}

Bitte beachten Sie, dass dem Schlüsselwort catch normalerweise ein Identifier folgt, der in runden Klammern steht. Dieser Identifier ähnelt einem Funktionsparameter. Wird eine Ausnahme abgefangen, wird der mit der Ausnahme verbundene Wert (z.B. ein Error-Objekt) diesem Parameter zugewiesen. Der mit einer catch-Klausel verbundene Identifier hat einen blockbezogenen Geltungsbereich – er ist nur innerhalb des catch-Blocks definiert.

Hier ist ein realitätsnahes Beispiel, in dem eine try/catch-Anweisung genutzt wird. Es verwendet die im vorhergehenden Abschnitt definierte factorial()-Methode und die clientseitigen JavaScript-Methoden prompt() und alert() für die Ein- und Ausgabe:

try {

// Den Benutzer bitte, eine Zahl einzugeben.

let n = Number(prompt("Please enter a positive integer", ""));

// Berechnen Sie die Fakultät der Zahl, vorausgesetzt, die Eingabe ist gültig.

let f = factorial(n);

// Zeigen Sie das Ergebnis an.

alert(n + "! = " + f);

}

catch(ex) { // Wenn die Eingabe des Benutzers nicht gültig war, landen wir hier.

alert(ex); // Teilen Sie dem Benutzer mit, welcher Fehler aufgetreten ist.

}

Dieses Beispiel zeigt eine try/catch-Anweisung ohne finally-Klausel. Obwohl finally seltener eingesetzt wird als catch, kann es hilfreich sein. Das Verhalten dieser Klausel verlangt allerdings zusätzliche Erläuterungen. Der finally-Block wird auf jeden Fall ausgeführt, wenn irgendein Teil des try-Blocks ausgeführt wird, unabhängig davon, auf welche Weise die Codeausführung im try-Block beendet wird. finally wird üblicherweise verwendet, um nach der Ausführung des try-Blocks aufzuräumen.

Im Normalfall erreicht der JavaScript-Interpreter das Ende des try-Blocks und fährt dann mit dem finally-Block fort, der diese eventuell nötigen Aufräumarbeiten durchführt. Verlässt der Interpreter den try-Block, weil er auf eine return-, continue- oder break-Anweisung gestoßen ist, wird der finally-Block ausgeführt, bevor der Interpreter zu seinem neuen Ziel springt.

Tritt im try-Block eine Ausnahme auf und ist ein zugehöriger catch-Block zur Behandlung der Ausnahme vorhanden, führt der Interpreter zuerst den catch- und dann den finally-Block aus. Gibt es keinen lokalen catch-Block, um die Ausnahme zu behandeln, führt der Interpreter zuerst den finally-Block aus und springt dann zur nächsten übergeordneten catch-Klausel.

Wenn ein finally-Block selbst einen Sprung mit einer return-, continue-, break- oder throw-Anweisung oder durch den Aufruf einer Methode verursacht, die eine Ausnahme auslöst, bricht der Interpreter den anhängigen Sprung zur übergeordneten catch-Klausel ab und führt den neuen Sprung durch. Löst beispielsweise ein finally-Block eine Ausnahme aus, ersetzt diese Ausnahme eine zuvor ausgelöste. Wird innerhalb eines finally-Blocks eine return-Anweisung angetroffen, wird diese normal ausgeführt, selbst wenn zuvor eine Ausnahme ausgelöst und noch nicht behandelt wurde.

try und finally können gemeinsam auch ohne catch-Klausel verwendet werden. In diesem Fall enthält der finally-Block einfach Aufräumcode, der garantiert ausgeführt wird, unabhängig davon, was im try-Block passiert. Bitte erinnern Sie sich daran, dass wir eine for-Schleife nicht vollständig durch eine while-Schleife nachbilden können, weil sich die continue-Anweisung bei beiden Schleifen unterschiedlich verhält. Wenn wir eine try/finally-Anweisung hinzufügen, können wir eine while-Schleife schreiben, die wie eine for-Schleife funktioniert und korrekt mit continue-Anweisungen umgeht:

// Simulation von: for( Initialisierung ; Prüfung ; Inkrementierung )

// Schleifenkörper ;

Initialisierung ;

while( Prüfung ) {

try { Schleifenkörper ; }

finally { Inkrementierung ; }

}

Da sich ein Schleifenkörper, der eine break-Anweisung enthält, in einer while-Schleife leicht anders verhält als in einer for-Schleife (weil eine zusätzliche Inkrementierung vor dem Verlassen der Schleife erfolgt), ist es selbst mithilfe einer finally-Klausel nicht möglich, die for-Schleife mit while vollständig zu simulieren.

JavaScript  –  Das Handbuch für die Praxis

Подняться наверх