From 074785cea106179cb3305637055ab0a009ca74f2 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:42:52 -0500 Subject: initial commit --- .../reference/statements/try...catch/index.html | 422 +++++++++++++++++++++ 1 file changed, 422 insertions(+) create mode 100644 files/ru/web/javascript/reference/statements/try...catch/index.html (limited to 'files/ru/web/javascript/reference/statements/try...catch/index.html') diff --git a/files/ru/web/javascript/reference/statements/try...catch/index.html b/files/ru/web/javascript/reference/statements/try...catch/index.html new file mode 100644 index 0000000000..3609136b03 --- /dev/null +++ b/files/ru/web/javascript/reference/statements/try...catch/index.html @@ -0,0 +1,422 @@ +--- +title: try...catch +slug: Web/JavaScript/Reference/Statements/try...catch +tags: + - JavaScript + - Исключение + - Ошибка +translation_of: Web/JavaScript/Reference/Statements/try...catch +--- +
{{jsSidebar("Statements")}}
+ +

Конструкция 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. +
  3. try {...} finally {...}
  4. +
  5. try {...} catch {...} finally {...}
  6. +
+ +

Блок catch содержит инструкции, которые будут выполнены, если в блоке try произошла ошибка. Если любая инструкция в блоке try выбрасывает исключение, то управление сразу же переходит в блок catch. Если в блок try не было выброшено исключение, то блок catch не выполняется.

+ +

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

+ +

Вы можете использовать вложенные конструкции try. Если внутренняя конструкция try не имеет блока catch (такое может быть при её использовании в виде try {...} finaly {...}, потому что try {...} не может быть без блоков catch или finally), будет вызван сatch внешней конструкции try.

+ +

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

+ +

Безусловный блок catch

+ +

При использовании блока catch, он вызывается для любого исключения в блоке try. Например, когда в следующем коде происходит ошибка, управление переходит к блоку catch.

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

Блок catch задает идентификатор (e в примере выше) который содержит объект исключения (в примере выше — значение, переданное оператору throw). Область видимости этого объекта ограничивается блоком catch.

+ +

Условный блок catch

+ +

"Условные блоки catch" можно создавать, используя try...catch с if...else if...else, как здесь:

+ +
try {
+  myroutine(); // может выбрасывать три вида исключений
+} catch (e) {
+  if (e instanceof TypeError) {
+    // обработка исключения TypeError
+  } else if (e instanceof RangeError) {
+    // обработка исключения RangeError
+  } else if (e instanceof EvalError) {
+    // обработка исключения EvalError
+  } else {
+    // обработка остальных исключений
+    logMyErrors(e); // передать обработчику ошибок
+  }
+}
+ +

Частый сценарий использованя — обработать известные исключения, а при неизвестных ошибках, пробросить их дальше:

+ +
try {
+  myRoutine();
+} catch(e) {
+  if (e instanceof RangeError) {
+    // обработка известного исключения, с которым
+    // понятно, что делать
+  } else {
+    throw e; // пробросить неизвестные ошибки
+  }
+}
+
+ +
+

Обратите внимание: Firefox раньше поддерживал краткую запись условных блоков catch:

+ +
try {
+  myroutine(); // может выбрасывать три вида исключения
+} catch (e if e instanceof TypeError) {
+  // обработка исключений TypeError
+} catch (e if e instanceof RangeError) {
+  // обработка исключений RangeError
+} catch (e if e instanceof EvalError) {
+  // обработка исключений EvalError
+} catch (e) {
+  // обработка остальных исключения
+  logMyErrors(e);
+}
+
+ +

Однако, такой синтаксис никогда не был частью спецификации ECMAScript и был удалён из Firefox после версии 59. Сейчас он не поддерживается ни в одном браузере.

+
+ +

Идентификатор исключения

+ +

Когда в блоке try выбрасывается исключение, exception_var (т. е. e в конструкции catch (e)) содержит значение исключения. Его можно использовать, чтобы получить больше информации об выброшенном исключении. Идентификатор доступен только в области видимости блока catch.

+ +
try {
+  if (!firstValidation()) {
+    throw 1;
+  }
+  if (!secondValidation()) {
+    throw 2;
+  }
+} catch (e) {
+  // Выводит 1 или 2 (если не произошло никакх других ошибок)
+  console.log(e);
+}
+ +

Блок finally

+ +

Блок finally содержит код который будет запущен после кода в блоках try и catch. Обратите внимание, что код в блоке finally запускается в независимости от того, было ли выброшено исключение или нет. Также код в блоке finally будет запущен вне зависимости от того, присутствует блок catch или нет. Блок finally можно использовать для того, чтобы скрипт безопасно завершил работу в случае ошибки. Например, если необходимо освободить память и ресурсы которые использовал скрипт.

+ +

Наличие специального блока, связанного с ошибкой, который выполняется вне зависимости от наличия исключительной ситуации, может показаться странным, но эта конструкция на самом деле весьма полезна. Рассмотрим пример кода:

+ +
function expensiveCalculations() {
+  // Сложные вычисления
+}
+
+function maybeThrowError() {
+  // Функция, которая может выбросить исключение
+  if(Math.random() > 0.5) throw new Error()
+}
+
+try {
+  // Теперь при прокрутке страницы будут происходить
+  // сложные вычисления, что сильно скажется на
+  // производительности
+  window.addEventListener('scroll', expensiveCalculations)
+  maybeThrowError()
+} catch {
+  // Если функция maybeThrowError выбросит исключения,
+  // управление сразу перейдёт в блок catch и
+  // сложные вычисления продолжат выполняться до
+  // перезагрузки страницы
+  maybeThrowError()
+}
+window.removeEventListener('scroll', expensiveCalculations)
+ +

В этом примере, если функция maybeThrowError выбросит исключение внутри блока try, управление перейдёт в блок catch. Если и в блоке catch эта функция тоже выбросит исключение, то выполнение кода прервётся, и обработчик события не будет снят, пока пользователь не перезагрузит страницу, что плохо скажется на скорости работы. Для того, чтобы избежать таких ситуаций, следует использовать блок finally:

+ +
try {
+  window.addEventListener('scroll', expensiveCalculations)
+  maybeThrowError()
+} catch {
+  maybeThrowError()
+} finally {
+  window.removeEventListener('scroll', expensiveCalculations)
+}
+
+
+ +

Другой пример: работа с файлами. В следующем фрагменте кода показывается, как скрипт открывает файл и записывает в него какие-то данные (в серверном окружении JavaScript имеет доступ к файловой системе). Во время записи может произойти ошибка. Но после открытия файл очень важно закрыть, потому что незакрытый файл может привести к утечкам памяти. В таких случях используется блок finally:

+ +
openMyFile();
+try {
+   // Сделать что-то с файлом
+   writeMyFile(theData);
+}
+finally {
+   closeMyFile(); // Закрыть файл, что бы ни произошло
+}
+
+ +

Примеры

+ +

Вложенные блоки try

+ +

Для начала давайте посмотрим что делает этот код:

+ +
try {
+  try {
+    throw new Error('упс');
+  }
+  finally {
+    console.log('finally');
+  }
+}
+catch (e) {
+  console.error('внешний блок catch', e.message);
+}
+
+// Вывод:
+// "finally"
+// "внешний блок catch" "упс"
+
+ +

Теперь отловим исключение во внутреннем блоке try, добавив к нему блок catch:

+ +
try {
+  try {
+    throw new Error('упс');
+  }
+  catch (e) {
+    console.error('внутренний блок catch', e.message);
+  }
+  finally {
+    console.log('finally');
+  }
+}
+catch (e) {
+  console.error('внешний блок catch', e.message);
+}
+
+// Output:
+// "внутренний блок catch" "упс"
+// "finally"
+
+ +

Наконец, пробросим ошибку

+ +
try {
+  try {
+    throw new Error('упс');
+  }
+  catch (e) {
+    console.error('внутренний блок catch', e.message);
+    throw e;
+  }
+  finally {
+    console.log('finally');
+  }
+}
+catch (e) {
+  console.error('внешний блок catch', e.message);
+}
+
+// Вывод:
+// "внутренний блок catch" "oops"
+// "finally"
+// "внешний блок catch" "oops"
+
+ +

Любое исключение будет передано только в ближайший блок catch, если он не пробросит его дальше. Все исключения, выброшенными внутренними блоками (потому что код в блоке catch также может выбросить исключение), будут пойманы внешними.

+ +

Возвращение значения из блока finally

+ +

Если блок finally возвращает какое-либо значение, оно становится значением, которое возвращает вся конструкция try...catch...finally, вне зависимости от любых инструкций return в блоках try и catch. Также игнорируются исключения, выброшенные блоком catch.

+ +
try {
+  try {
+    throw new Error('упс');
+  }
+  catch (e) {
+    console.error('внутренний блок catch', e.message);
+    throw e;
+  }
+  finally {
+    console.log('finally');
+    return;
+  }
+}
+catch (e) {
+  console.error('внешний блок catch', e.message);
+}
+
+// Output:
+// "внутренний блок catch" "упс"
+// "finally"
+
+ +

"упс" не доходит до внешнего блока из-за инструкции return в блоке finally. То же самое произойдёт с любым значением, возвращаемым из блока catch.

+ +

Спецификации

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
СпецификацияСостояниеПримечание
{{SpecName('ES3')}}{{Spec2('ES3')}}Изначальная редакция. Реализовано в JavaScript 1.4
{{SpecName('ES5.1', '#sec-12.14', 'try statement')}}{{Spec2('ES5.1')}}
{{SpecName('ES6', '#sec-try-statement', 'try statement')}}{{Spec2('ES6')}}
{{SpecName('ESDraft', '#sec-try-statement', 'try statement')}}{{Spec2('ESDraft')}}Not part of the current ECMA-262 standard: Multiple catch clauses and conditional clauses (SpiderMonkey extension, JavaScript 1.5).
+ +

Совместимость

+ +

{{CompatibilityTable}}

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureChromeFirefox (Gecko)Internet ExplorerOperaSafari
Basic support{{CompatVersionUnknown}}{{CompatGeckoDesktop("6")}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}
Conditional clauses
+ (non-standard)
{{CompatNo}}{{CompatVersionUnknown}}{{CompatNo}}{{CompatNo}}{{CompatNo}}
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureAndroidChrome for AndroidFirefox Mobile (Gecko)IE MobileOpera MobileSafari Mobile
Basic support{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}{{CompatVersionUnknown}}
Conditional clauses
+ (non-standard)
{{CompatNo}}{{CompatNo}}{{CompatVersionUnknown}}{{CompatNo}}{{CompatNo}}{{CompatNo}}
+
+ +

См. также

+ + -- cgit v1.2.3-54-g00ecf