--- title: try...catch slug: Web/JavaScript/Reference/Statements/try...catch tags: - JavaScript - Исключение - Ошибка translation_of: Web/JavaScript/Reference/Statements/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_statementscatch_statements_1, catch_statements_2Инструкции, которые будут выполнены, если произойдёт ошибка в блоке try.
exception_var_1, exception_var_2catchcondition_1finally_statementstry. Выполнение происходит в независимости от того, произошла ошибка или нет.Конструкция try содержит блок try, в котором находится одна или несколько инструкций (Блок ({} ) обязательно должен присутствовать, даже если выполняется всего одна инструкция), и хотя бы один блок catch или finally. Таким образом, есть три основные формы конструкции try:
try {...} catch {...}try {...} finally {...}try {...} catch {...} finally {...}Блок 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, он вызывается для любого исключения в блоке 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 содержит код который будет запущен после кода в блоках 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 {
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 возвращает какое-либо значение, оно становится значением, которое возвращает вся конструкция 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.
{{Compat}}