try...catch

Diese Übersetzung ist unvollständig. Bitte helfen Sie, diesen Artikel aus dem Englischen zu übersetzen.

Die try...catch-Anweisung (sinngemäß: testen und verarbeiten) rahmt einen Block von Anweisungen (try statements) ein und legt Reaktionen (catch statementes) fest, die im Fehlerfall ausgeführt werden.

Syntax

try {
   try_Anweisungen
}
[catch (Fehler_var_1 if Bedingung_1) { // nicht Standard
   catch_Anweisungen
}]
...
[catch (Fehler_var_2) {
   catch_Anweisungen_2
}]
[finally {
   finally_Anweisungen
}]
try_Anweisungen
Die auszuführenden Anweisungen.
catch_Anweisungen_1, catch_Anweisungen_2
Anweisungen, die ausgeführt werden, wenn bei den try-Anweisungen ein Fehler auftritt.
Fehler_var_1, Fehler_var_2
Ein Bezeichner der das Fehlerobjekt des zugehörigen catch-Abschnitts enthält.
Bedingung_1
Ein Bedingungsausdruck.
finally_Anweisungen
Die Schlussanweisungen werden nach den try-Anweisungen ausgeführt. Die Anweisungen werden immer ausgeführt, auch wenn ein Fehler ausgegeben wurde. 

Beschreibung

Der try-Block besteht aus einer oder mehreren Anweisungen (der Absschnitt steht – auch bei nur einer Zeile – immer in geschweiften Klammern {}), mindestens einem catch- oder einem finally-Abschnitt oder beiden. Es gibt also drei Arten von try-Anweisungen:

  1. try...catch
  2. try...finally
  3. try...catch...finally

Der catch-Abschnitt enthält Anweisungen für den Fall, dass im try-Abschnitt ein Fehler auftritt. Der try-Block soll erfolgreich ausgeführt werden. Wenn das nicht der Fall ist, dann soll die Kontrolle an den catch-Block übergeben werden. Bei einer fehlerhaften Anweisung im Block im try-Abschnitt – oder in Funktionen, die von dort aufgerufen werden – geht die Kontrolle sofort an den catch-Abschnitt über. Wird kein Fehler gemeldet wird der catch-Abschnitt nicht ausgeführt.

Der finally-Abschnitt wird nach dem try- und dem catch-Abschnitt ausgeführt, vor den Anweisungen, die dem try-Abschnitt folgen. Der Abschnitt wird immer ausgeführt, ob ein Fehler aufgetreten ist oder nicht.

Mehrer try-Anweisungen können verschachtelt werden. Wenn ein innerer try-Block keinen catch-Abschnitt hat wird der catch-Abschnitt des nächsthöheren try-Blocks ausgeführt.

Mit der try-Anweisungen können auch JavaScript-Fehler bearbeitet werden. Mehr zur Fehlerbearbeitung in JavaScript steht im JavaScript Guide.

Unbhängiger catch-Abschnitt

Wenn mit einem einzelnen, ungebundenen catch-Abschnitt gearbeitet wird, dann wird der catch-Block bei jedem Fehler durchlaufen. Wenn der Fehler im folgenden Beispiel-Code auftritt geht die Kontrolle an den catch-Abschnitt über.

try {
   throw "myException"; // Fehler wird ausgelöst
}
catch (e) {
   // Anweisungen für jeden Fehler
   logMyErrors(e); // Fehler-Objekt an die Error-Funktion geben
}

Im catch-Block wird ein Bezeichner festgelegt (e im Beispiel), die den Wert enthält, der durch die throw-Anweisung entstanden ist. Der catch-Block ist besonders, weil er zu Beginn der Ausführung einen Bezeichner anlegt, der für den gesamten Block gilt. Wenn der catch-Block abgearbeitet ist steht der Bezeichner nicht mehr zur Verfügung.

Abhängige catch-Abschnitte

Kein Standard
Diese Funktion entspricht nicht dem Standard und ist nicht Teil der Standardisierung. Diese Funktion darf nicht in Webseiten, die via das Internet zugänglich sind, benutzt werden: Sie wird nicht für alle Nutzer funktionieren. Es kann zu umfangreichen Inkompatibilitäten zwischen verschiedenen Implementierungen kommen und die Funktionsweise oder Eigenschaften könnten in der Zukunft verändert werden.

Mehrere abhängige catch-Abschnitte können spezifische Fehler bearbeiten. In diesem Fall wird der passende catch-Abschnitt aufgerufen, wenn der zugehörige Fehler aufgetreten ist. Im folgenden Beispiel kann der Code im try-Block drei mögliche Fehler ausgeben: TypeError, RangeError, and EvalError (Typ-Fehler, Bereich-Fehler und Rechenfehler). Wenn ein Fehler auftritt geht die Kontrolle an den zugehörigen catch-Abschnitt. Wenn dem Fehler kein catch-Abschnitt entspricht und ein unabhäniger catch-Abschnitt vorhanden ist, geht die Kontrolle an ihn.

Wenn mehrere abhängige catch-Abschnitt mit einem unabhängigen kombiniert werden, muss der unabhängige Abschnitt am Ende stehen: er fängt sonst alle Fehlertypen ab bevor sie die eigenen, abhängigen Abschnitte erreichen.

Zu Erinnerung: diese Funktionalität ist kein Teil der ECMAScript-Spezifikation.

try {
    myroutine(); // erzeugt drei mögliche Fehlertypen
} catch (e if e instanceof TypeError) {
    // Anweisungen für die verschiedenen Fehlertypen
} catch (e if e instanceof RangeError) {
    // Anweisungen für Bereichsfehler
} catch (e if e instanceof EvalError) {
    // Anweisungen für Berechnungsfehler
} catch (e) {
    // Anweisungen für nicht festgelegte Fehlertypen 
    logMyErrors(e); // Objekt an die Fehler-Funktion geben
}

Das nächste Beispiel zeigt, wie die gleichen "abhängigen catch-Abschnitte" aussehen, wenn einfaches JavaScript benutzt wird, das den ECMAScript-Spezifikationen entspricht (etwas umfangreicher, funktioniert aber genauso).

try {
    myroutine(); // erzeugt drei mögliche Fehlertypen
} catch (e) {
    if (e instanceof TypeError) {
        // Anweisungen für die verschiedenen Fehlertypen
    } else if (e instanceof RangeError) {
        // Anweisungen für Bereichsfehler
    } else if (e instanceof EvalError) {
        // Anweisungen für Berechnungsfehler
    } else {
       // Anweisungen für nicht festgelegte Fehlertypen
       logMyErrors(e); // Objekt an die Fehler-Funktion geben
    }
}

Der Fehler-Bezeichner

Wenn im try-Block ein Fehler auftritt, enthält die exception_var (z.B. das e in catch(e)) den Wert, der durch die throw-Anweisung erzeugt wird. Mit diesem Bezeichner können also Informationen über den Fehler gewonnen werden.

Der Bezeichner gilt nur innerhalb des catch-Abschnitts. Er wird zu Beginn des Abschnitts angelegt und steht nach der Abarbeitung nicht mehr zur Verfügung.

Der finally-Abschnitt

Zum Abschluss-Abschnitt (finally) gehören die Anweisungen, die nach dem try- und dem catch-Block ausgeführt werden, noch bevor irgenwelche Anweisugnen nach den try-/catch-/finally-Abschnitten ausgeführt werden. Der finally-Abschnitt wird immer ausgeführt, auch wenn bei der Verarbeitung ein Fehler aufgetreten ist. Er wird auch ausgeführt, wenn kein catch-Abschnitt den Fehler bearbeitet. Der finally-Abschnitt kann dabei helfen, das eigene Script im Fehlerfall anständig zu beenden. Dort können zum Beispiel für ein übergreifendes Aufräumen Ressourcen wieder freigegeben werden, die durch das Script gebunden wurden.

Vielleicht sieht ein Abschnitt, der sich auf Fehler bezieht, aber UNABHÄNGIG vom tatsächlichen Auftreten eines Fehlers immer ausgeführt wird, merkwürdig aus. Aber dieses Konstrukt dient tatsächlich einem Zweck. Wichtig dabei ist nicht, dass der finally-Abschnitt immer aussgeführt wird, sonder das der normale Code nach einem try...catch NICHT ausgeführt wird. Wenn zum Beispiel in einem catch-Abschnitt, der zu einem try-Block gehört, ein Fehler auftritt, dann wird nichts von dem umgebenden Code ausgeführt, gleichgültig ob es ein umgebende try-catch-Blöcke oder normale Anweisungen sind. Die Kontrolle wird stattdessen an den catch-Abschnitt übergeben, der zum umgebenden try-Abschnitt gehört oder – wenn es den nicht gibt – an die interne Fehlerroutine. 

Auf diese Weise wird jeder nachfolgende Aufräum-Code im eingeschlossenen Abschnitt oder im normalen Programmablauf übersprungen. Wenn aber zum try-Abschnitt ein finally-Abschnitt gehört, dann kann in diesem Abschnitt aufgeräumt werden, bevor es in einen umgebenden catch-Abschnitt (oder den Fehlergenerator) geht, der dann den zweiten Fehler bearbeitet. 

Wenn unabhängig vom Erfolg des try...catch-Blocks aufgeräumt werden muss und der finally-Abschnitt nur nach einem Fehler ausgeführt würde, dann müsste der Aufräum-Code doppelt verwendet werden, innerhalb und außerhalb des finally-Abschnitts. Deshalb wird der finally-Block unabhängig von auftretenden Fehlern ausgeführt.

Das folgende Beispiel öffnet eine Datei und führt dann Anweisungen aus, die mit der Datei arbeiten (server-seitiges JavaScript lässt den Zugriff auf Dateien zu).  Wenn ein Fehler ausgegeben wird solange die Datei geöffnet ist, dann schließt der finally-Abschnitt diese Datei bevor das Script stoppt. Der Code im Abschnitt wird auch bei Returns aus try- oder catch-Blöcken ausgeführt.

openMyFile()
try {
   // bindet eine Ressource
   writeMyFile(theData);
}
finally {
   closeMyFile(); // Ressource immer wieder frei geben
}

Examples

Verschachtelte try-Blöcke

Zuerst einmal untersuchen wir diese Beispiele:

try {
  try {
    throw new Error("oops");
  }
  finally {
    console.log("finally");
  }
}
catch (ex) {
  console.error("outer", ex.message);
}

// Output:
// "finally"
// "outer" "oops"

Wenn wir den Fehler im inneren try-Block mit einem catch-Abschnitt bearbeiten

try {
  try {
    throw new Error("oops");
  }
  catch (ex) {
    console.error("inner", ex.message);
  }
  finally {
    console.log("finally");
  }
}
catch (ex) {
  console.error("outer", ex.message);
}

// Output:
// "inner" "oops"
// "finally"

Und jetzt wird der Fehler im catch-Abschnitt noch einmal produziert:

try {
  try {
    throw new Error("oops");
  }
  catch (ex) {
    console.error("inner", ex.message);
    throw ex;
  }
  finally {
    console.log("finally");
  }
}
catch (ex) {
  console.error("outer", ex.message);
}

// Output:
// "inner" "oops"
// "finally"
// "outer" "oops"

Jeder auftretende Fehler wird nur einmal bearbeitet, durch den nächsten umgebenden catch-Block (es sei denn, er wird erneut ausgegeben). Natürlich werden alle im inneren Abschnitt neu auftretenden Fehler durch den umschließenden Block bearbeitet.

Rückgaben aus einem finally-Block

Wenn der finally-Abschnitt ein Wert  zurückgibt, wird dieser Wert zum Rückgabewert der gesamten try-catch-finally-Veranstaltung, unabhänig von allen return-Anweisungen in den try- oder catch-Blöcken. Das gitl auch für Fehler im catch-Block:

try {
  try {
    throw new Error("oops");
  }
  catch (ex) {
    console.error("inner", ex.message);
    throw ex;
  }
  finally {
    console.log("finally");
    return;
  }
}
catch (ex) {
  console.error("outer", ex.message);
}

// Output:
// "inner" "oops"
// "finally"

Der äußere "oops"-Fehler wird nicht ausgelöst wegen des return im finally-Block. Das gleich gilr für alle Werte, die aus dem catch-Abschnitt zurück gegeben werden.

Spezifikationen

Spezifikation Status Kommentar
ECMAScript 3rd Edition (ECMA-262) Standard Erste Definition. Implementiert in JavaScript 1.4
ECMAScript 5.1 (ECMA-262)
Die Definition von 'try statement' in dieser Spezifikation.
Standard  
ECMAScript 2015 (6th Edition, ECMA-262)
Die Definition von 'try statement' in dieser Spezifikation.
Standard  
ECMAScript 2017 Draft (ECMA-262)
Die Definition von 'try statement' in dieser Spezifikation.
Entwurf

Fällt nicht unter den aktuellen ECMA-262-Standard: Mehrfache catch-Abschnitte und abhängige Abschnitte (SpiderMonkey extension, JavaScript 1.5).

Browser-Verträglichkeit

Funktion Chrome Firefox (Gecko) Internet Explorer Opera Safari
Grundunter-stützung (Ja) 6 (6) (Ja) (Ja) (Ja)
Abhängige Abschnitte
(Non-Standard)
Nicht unterstützt (Ja) Nicht unterstützt Nicht unterstützt Nicht unterstützt
Funktion Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Grundunter-stützung  
(Ja) (Ja) (Ja) (Ja) (Ja) (Ja)
Abhängige Abschnitte
(Non-Standard)
 
Nicht unterstützt Nicht unterstützt (Ja) Nicht unterstützt Nicht unterstützt Nicht unterstützt

Siehe auch

Schlagwörter des Dokuments und Mitwirkende

 Mitwirkende an dieser Seite: stepdate
 Zuletzt aktualisiert von: stepdate,