try...catch

Перевод не завершен. Пожалуйста, помогите перевести эту статью с английского.

Конструкция try...catch помечает блок инструкций как try, и в зависимости от того, произошла ошибка или нет, вызывает дополнительный блок инструкций catch.

Синтаксис

try {
   try_statements
}
[catch (exception_var_1 if condition_1) { // не стандартно
   catch_statements_1
}]
...
[catch (exception_var_2) {
   catch_statements_2
}]
[finally {
   finally_statements
}]
try_statements
Инструкция, которая будет выполнена.
catch_statements_1, catch_statements_2

Инструкции, которые будут выполнены, если произойдёт ошибка в блоке try.

exception_var_1, exception_var_2
Идентификатор для хранения объекта ошибки, который впоследствии используется в блоке catch
condition_1
Выражение состояния
finally_statements
Инструкции, которые выполняются после завершения блока try. Выполнение происходит независимо от того, была ошибка или нет.

Описание

Конструкция try содержит блок try, в котором находится одна или несколько инструкций ({} должно быть всегда использовано, даже для одиночных инструкций), и как минимум один блок catch, или один блок finally, или оба. Здесь приведены три возможных варианта использования конструкции try:

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

Блок catch содержит инструкции, которые будут выполнены, если в блоке try произошла ошибка. Это сделано для того, чтобы была возможность обработать ошибку в блоке catch, при её возникновении. Если какая-либо инструкция вызывает ошибку в try блоке, то управление незамедлительно переходит в блок catch. Если в try блоке не будет никакой ошибки, то блок catch пропустится.

Блок finally выполнится после выполнения блоков try и catch, но перед инструкциями, следующими за конструкцией try...catch. Этот блок всегда выполняется независимо от того, была ошибка или нет.

Вы можете размещать один или более try оператор. Если внутренний try оператор не имеет catch блок, будет использован сatch внешнего оператора try.

Вы также можете использовать оператор try для обработки JavaScript исключений. Загляните в JavaScript руководство для получения большей информации о JavaScript исключениях.

Специальный вызов ошибки

При специальном вызове ошибки, вход в блок catch происходит тогда, когда ошибка вызвана. Для примера, когда ошибка 'myException вызывается в следующем коде, управление переходит в блок catch незамедлительно:

try {
   throw 'myException'; // создание ошибки
}
catch (e) {
   // инструкции для работы с ошибками
   logMyErrors(e); // передает объект ошибки для управления им
}

Блок catch задает идентификатор (e в примере выше) который содержит заданное оператором throw. Блок catch в JavaScript создает идентификатор когда произошел вход в блок и добавляет его в область видимости блока; идентификатор действителен только во время исполнения блока catch; после того, как catch блок заканчивает свое исполнение идентификатор перестаёт быть доступным.

Conditional catch clauses

Не стандартно
Эта возможность не является стандартной и стандартизировать её пока никто не собирается. Не используйте её на сайтах, смотрящих во внешний мир: она будет работать не у всех пользователей. Также могут присутствовать большие несовместимости между реализациями и её поведение может в будущем измениться.

You can also use one or more conditional catch clauses to handle specific exceptions. In this case, the appropriate catch clause is entered when the specified exception is thrown. In the following example, code in the try block can potentially throw three exceptions: TypeError, RangeError, and EvalError. When an exception occurs, control transfers to the appropriate catch clause. If the exception is not one of the specified exceptions and an unconditional catch clause is found, control transfers to that catch clause.

If you use an unconditional catch clause with one or more conditional catch clauses, the unconditional catch clause must be specified last. Otherwise, the unconditional catch clause will intercept all types of exception before they can reach the conditional ones.

Reminder: this functionality is not part of the ECMAScript specification.

try {
    myroutine(); // may throw three types of exceptions
} catch (e if e instanceof TypeError) {
    // statements to handle TypeError exceptions
} catch (e if e instanceof RangeError) {
    // statements to handle RangeError exceptions
} catch (e if e instanceof EvalError) {
    // statements to handle EvalError exceptions
} catch (e) {
    // statements to handle any unspecified exceptions
    logMyErrors(e); // pass exception object to error handler
}

And here is how to do implement the same "Conditional catch clauses" using only simple JavaScript conforming to the ECMAScript specification (obviously it's more verbose, but works everywhere):

try {
    myroutine(); // may throw three types of exceptions
} catch (e) {
    if (e instanceof TypeError) {
        // statements to handle TypeError exceptions
    } else if (e instanceof RangeError) {
        // statements to handle RangeError exceptions
    } else if (e instanceof EvalError) {
        // statements to handle EvalError exceptions
    } else {
       // statements to handle any unspecified exceptions
       logMyErrors(e); // pass exception object to error handler
    }
}

The exception identifier

When an exception is thrown in the try block, exception_var (e.g. the e in catch (e)) holds the value specified by the throw statement. You can use this identifier to get information about the exception that was thrown.

This identifier is local to the catch clause. That is, it is created when the catch clause is entered, and after the catch clause finishes executing, the identifier is no longer available.

The finally clause

The finally clause contains statements to execute after the try block and catch clause(s) execute, but before the statements following the try..catch..finally block. Note that the finally clause executes regardless of whether or not an exception is thrown. Also, if an exception is thrown, the statements in the finally clause execute even if no catch clause handles the exception.  You can use the finally clause to make your script fail gracefully when an exception occurs; for example, to do general cleanup, you may need to release a resource that your script has tied up.

It may seem strange to have a special exception-related clause that executes REGARDLESS of whether there is an exception, but this construct actually does serve a purpose.  The important point though, is not that the finally-clause always executes, but rather that ordinary code otherwise following a try..catch, does not.  For instance, if another exception occurs inside a try's catch-block, any remaining code in the same outer try-block enclosing that try..catch (or in the main flow, if not in an outer try-block) , will not get executed, since control is immediately transferred to the outer try's catch-block (or the internal error-generator, if not in a try-block).  Thus, any routine cleanup code done in that enclosed (or the main) section before it exits, will be skipped.  However, If the try-block has a finally-block, then that finally-block code will be executed first to permit any such cleanup, and THEN the other try's catch-block (or the error-generator) will get control to handle the second exception.  Now, if that routine cleanup must be done whether or not the try..catch code succeeds, then if the finally-block only executed after an exception, the same cleanup code would have to be duplicated both inside and outside the finally-block, and therefore there is no reason not to have just the finally-block alone, and let it execute regardless of exceptions or not.

The following example opens a file and then executes statements that use the file (server-side JavaScript allows you to access files). If an exception is thrown while the file is open, the finally clause closes the file before the script fails. The code in finally also executes upon explicitly returning from try or catch block.

openMyFile();
try {
   // tie up a resource
   writeMyFile(theData);
}
finally {
   closeMyFile(); // always close the resource
}

Examples

Nested try-blocks

First let's see what happens with this:

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

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

Now, if we already caught the exception in the inner try-block by adding a catch block

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"

And now, lets re-throw the error.

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"

Any given exception will be caught only once by the nearest enclosing catch-block, unless it is re-thrown. Of course, any new exceptions raised in the "inner" block (because code in catch-block may do something that throws), will be caught by the "outer" block.

Returning from a finally block

If the finally block returns a value, this value becomes the return value of the entire try-catch-finally production, regardless of any return statements in the try and catch blocks. This includes exceptions thrown inside of the 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"

The outer "oops" is not thrown because of the return in the finally block. The same would apply to any value returned from the catch block.

Specifications

Specification Status Comment
ECMAScript 3rd Edition (ECMA-262) Стандарт Initial definition. Implemented in JavaScript 1.4
ECMAScript 5.1 (ECMA-262)
Определение 'try statement' в этой спецификации.
Стандарт  
ECMAScript 2015 (6th Edition, ECMA-262)
Определение 'try statement' в этой спецификации.
Стандарт  
ECMAScript 2017 Draft (ECMA-262)
Определение 'try statement' в этой спецификации.
Черновик Not part of the current ECMA-262 standard: Multiple catch clauses and conditional clauses (SpiderMonkey extension, JavaScript 1.5).

Browser compatibility

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support (Да) 6 (6) (Да) (Да) (Да)
Conditional clauses
(non-standard)
Нет (Да) Нет Нет Нет
Feature Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support (Да) (Да) (Да) (Да) (Да) (Да)
Conditional clauses
(non-standard)
Нет Нет (Да) Нет Нет Нет

See also

Метки документа и участники

 Внесли вклад в эту страницу: nikitaermishin, NikitaCoder
 Обновлялась последний раз: nikitaermishin,