--- title: try...catch slug: Web/JavaScript/Reference/Statements/try...catch tags: - Error - JavaScript - виняток - помилка translation_of: Web/JavaScript/Reference/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
:
try...catch
try...finally
try...catch...finally
Блок catch
містить команди, які визначають, що робити, якщо викинуто виняток у блоці try
. Отже, ви хочете, щоб блок try
виконався успішно, а в разі неуспіху ви хочете передати контроль до блоку catch
. В разі, якщо будь-який вираз всередині блоку try
(або функція, викликана зсередини блоку try
) викидає виняток, контроль негайно переходить до блоку catch
. Якщо жодних винятків у блоці try
не було викинуто, блок catch
пропускається.
Блок finally
виконується після виконання блоків try
та catch
, але до команд, що йдуть після виразу try
. Він завжди виконується, незалежно від того, чи було викинуто або перехоплено виняток.
Ви можете створити один або більше вкладених виразів try
. Якщо внутрішній try
не має блоку catch
, контроль передається у блок catch
зовнішнього try
.
Ви також можете використовувати try
, щоб обробляти винятки JavaScript. Ви знайдете більше інформації щодо винятків JavaScript у Посібнику JavaScript.
catch
Коли використовується один безумовний блок catch
, перехід у catch
відбувається у випадку викидання будь-якого винятку. Наприклад, коли виняток стається у наступному коді, контроль передається до блоку catch
.
try { throw 'myException'; // генерує виняток } catch (e) { // команди обробки будь-яких винятків logMyErrors(e); // передає об'єкт винятку до обробника помилок }
Блок catch
вказує ідентифікатор (e
у наведеному прикладі), який містить значення, визначене у операторі throw
. Блок catch
унікальний тим, що JavaScript створює цей ідентифікатор при вході у блок catch
, а також додає його у область видимості; ідентифікатор "живе" тільки протягом виконання блоку catch
; коли catch
завершується, ідентифікатор більше недоступний.
catch
{{non-standard_header}}
Ви також можете використати один або декілька умовних блоків catch
для обробки специфічних винятків. В цьому випадку вхід у відповідний блок catch
відбувається, коли викидається вказаний виняток. У наступному прикладі код у блоці try
може викинути один з трьох винятків: {{jsxref("TypeError")}}, {{jsxref("RangeError")}} або {{jsxref("EvalError")}}. Коли виникає виняток, контроль передається до відповідного блоку catch
. Якщо виняток не є одним із вказаних, і був знайдений безумовний блок catch
, контроль передається до цього блоку catch
.
Якщо ви використовуєте безумовний catch
з одним або кількома умовними блоками catch
, безумовний catch
має бути вказаний останнім. Інакше безумовний catch
перехоплюватиме всі види винятків до того, як вони потраплять в умовні блоки.
Нагадування: ця функціональність не є частиною специфікації ECMAScript і ніколи не прибиралася з Firefox 59. Вона більше не підтримується у жодних сучасних веб-переглядачах.
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); // передати об'єкт винятку до обробника помилок }
Ось такі ж "Умовні блоки catch", написані кодом, що відповідає специфікації ECMAScript (він доволі багатослівний, зате працює всюди):
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
, ідентифікатор exception_var
(наприклад, e
у catch (e)
) містить значення, вказане у виразі throw
. Ви можете скористатись цим ідентифікатором, щоб отримати інформацію про виняток. Це локальний ідентифікатор блоку catch
. Тобто, він створюється при вході у catch
, а після того, як виконання блоку catch
завершується, ідентифікатор більше недоступний.
function isValidJSON(text) { try { JSON.parse(text); return true; } catch { return false; } }
finally
Блок finally
містить команди, які виконуються після виконання блоків try
та catch
, але до команд, що розташовані після конструкції try...catch...finally
. Зверніть увагу, що finally
виконується незалежно від того, чи був викинутий виняток. Також, якщо виняток було викинуто, команди блоку finally
виконуються навіть якщо немає блоку catch
, щоб обробити виняток.
Ви можете скористатись блоком finally
, щоб у разі викидання винятку ваш скрипт переривався красиво; наприклад, вам може знадобитися звільнити ресурс, до якого був прив'язаний ваш скрипт.
Це може виглядати дивним, мати спеціальний блок, пов'язаний з винятками, що виконується незалежно від того, чи стався виняток, але ця конструкція насправді виконує свою задачу. Важливим моментом є те, що блок finally
виконується завжди, на відміну від звичайного коду, розташованого після try...catch
.
Наприклад, якщо станеться інший виняток всередині catch
цього try
, будь-який код, що не був виконаний у зовнішньому try
, що замикає цей try...catch
(або у головному потоці, якщо виконувався не зовнішній try
), не буде виконаний, оскільки контроль негайно перейде до блоку catch
зовнішнього try
(або до внутнішнього генератора помилок, якщо виконується не блок try
).
Таким чином, будь який поточний код очистки, що виконується у цій зовнішній (або головній) секції перед закінченням, буде пропущений. Однак, якщо вираз try
містить блок finally
, то спочатку буде виконаний код блоку finally
, дозволяючи зробити очистку, і тільки ПОТІМ контроль буде передано до блоку catch
іншого try
(або до генератора помилок) для обробки винятку.
Отже, якщо поточна очистка повинна бути зроблена, не зважаючи на те, чи успішно виконаний код у try...catch
, тоді, якби блок finally
виконувався тільки після винятку, той самий код очистки довелося б повторювати і всередині, і поза блоком finally
, і, таким чином, немає причини не мати один лише блок finally
, який виконується незалежно від того, стався виняток чи ні.
Наступний приклад відкриває файл і далі виконує команди, які використовують цей файл (JavaScript на стороні сервера дозволяє звертатись до файлів). Якщо викидається виняток, доки файл відкритий, блок finally
закриває цей файл до того, як скрипт переривається. Код у блоці finally
також виконується з явним поверненням з блоку try
або catch
.
openMyFile(); try { // прив'язати ресурс writeMyFile(theData); } finally { closeMyFile(); // завжди закривати ресурс }
Спочатку подивимось, що відбувається тут:
try { try { throw new Error('ой-ой'); } finally { console.log('finally'); } } catch (ex) { console.error('зовнішній', ex.message); } // Результат: // "finally" // "зовнішній" "ой-ой"
Тепер, якщо ми вже перехопили виняток у внутрішньому try, додавши блок catch.
try { try { throw new Error('ой-ой'); } catch (ex) { console.error('внутрішній', ex.message); } finally { console.log('finally'); } } catch (ex) { console.error('зовнішній', ex.message); } // Результат: // "внутрішній" "ой-ой" // "finally"
А тепер викинемо цю помилку повторно.
try { try { throw new Error('ой-ой'); } catch (ex) { console.error('внутрішній', ex.message); throw ex; } finally { console.log('finally'); } } catch (ex) { console.error('зовнішній', ex.message); } // Результат: // "внутрішній" "ой-ой" // "finally" // "зовнішній" "ой-ой"
Будь-який виняток буде перехоплений лише один раз найближчим замикаючим блоком catch, якщо тільки він не був викинутий повторно. Звісно, будь-які нові винятки, викинуті у "внутрішньому" блоці (бо код у блоці catch може зробити те, що викине помилку), будуть перехоплені "зовнішнім" блоком.
Якщо блок finally
повертає значення, це значення повертається усією конструкцією try-catch-finally
, не зважаючи на будь-які інші оператори return
у блоках try
та catch
. Це стосується й винятків, викинутих всередині блоку catch:
(function() { try { try { throw new Error('ой-ой'); } catch (ex) { console.error('внутрішній', ex.message); throw ex; } finally { console.log('finally'); return; } } catch (ex) { console.error('зовнішній', ex.message); } })(); // Результат: // "внутрішній" "ой-ой" // "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')}} | Не є частиною нинішнього стандарту ECMA-262: Використання кількох блоків catch та умовні блоки (розширення SpiderMonkey, JavaScript 1.5). |
{{Compat("javascript.statements.try_catch")}}