Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

translation(JS): web/javascript/reference/statements/try...catch #510

Merged
merged 5 commits into from
Sep 22, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
270 changes: 270 additions & 0 deletions files/uk/web/javascript/reference/statements/try...catch/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
---
title: try...catch
slug: Web/JavaScript/Reference/Statements/try...catch
tags:
- Exception
- JavaScript
- Language feature
- Statement
browser-compat: javascript.statements.try_catch
---

{{jsSidebar("Statements")}}

Інструкція **`try...catch`** (спробувати-перехопити) складається з блока `try` і або блока `catch`, або блока `finally`, або їх обох. Код в блоку `try` виконується першим, і якщо він викидає виняток, то виконується код у блоку `catch`. Код у блоку `finally` виконується в будь-якому випадку, перед тим, як контроль виконання полишає всю конструкцію.

{{EmbedInteractiveExample("pages/js/statement-trycatch.html")}}

## Синтаксис

```js-nolint
try {
tryStatements
} catch (exceptionVar) {
catchStatements
} finally {
finallyStatements
}
```

- `tryStatements`
- : Інструкції до виконання.
- `catchStatements`
- : Інструкція, що виконується, коли блок `try` викидає виняток.
- `exceptionVar` {{optional_inline}}
- : Необов'язковий ідентифікатор, що містить перехоплений виняток для відповідного блока `catch`. Якщо блок `catch` не використовує значення винятку, то можна опустити `exceptionVar` і дужки біля нього: `catch {...}`.
- `finallyStatements`
- : Інструкції, що виконуються перед тим, як контроль виконання виходить з конструкції `try...catch...finally`. Ці інструкції виконуються незалежно від того, чи був викинутий або перехоплений виняток.

## Опис

Інструкція `try` завжди починається з блока `try`. Далі має бути або блок `catch`, або блок `finally`, або вони обидва. Відтак – три варіанти інструкції `try`:

- `try...catch`
- `try...finally`
- `try...catch...finally`

На відміну від інших конструкцій, як то [`if`](/uk/docs/Web/JavaScript/Reference/Statements/if...else) чи [`for`](/uk/docs/Web/JavaScript/Reference/Statements/for), блоки `try`, `catch` і `finally` мусять бути _блоками_, а не одиничними інструкціями.

```js example-bad
try doSomething(); // SyntaxError
catch (e) console.log(e);
```

Блок `catch` містить інструкції, котрі вказують, що робити, якщо блок `try` викинув виняток. Якщо будь-яка інструкція всередині блока `try` (або в функції, викликаної зсередини блока `try`) викидає виняток, контроль негайно переходить до блока `catch`. Якщо в блоку `try` не викидається жодний виняток, то блок `catch` пропускається.

Блок `finally` обов'язково буде виконаний перед виходом контролю виконання з конструкції `try...catch...finally`. Він завжди виконується, незалежно від того, чи було викинуто або перехоплено виняток.

Інструкції `try` можна вкладати одну в одну. Якщо внутрішня інструкція `try` не має блока `catch`, то використовується блок `catch` зовнішньої `try`.

Також інструкцію `try` можна застосовувати для обробки винятків JavaScript. Дивіться [Посібник з JavaScript](/uk/docs/Web/JavaScript/Guide) для отримання подробиць щодо винятків JavaScript.

### Безумовний блок catch

Коли застосовується блок `catch`, блок `catch` виконується, коли зсередини блока `try` викидається будь-який виняток. Наприклад, коли в наступному коді трапляється виняток, контроль переходить до блоку `catch`.

```js
try {
throw 'myException'; // породжує виняток
} catch (e) {
// інструкції для обробки будь-яких винятків
logMyErrors(e); // передати об'єкт винятку обробнику помилок
}
```

Блок `catch` вказує ідентифікатор (`e` в прикладі вище), котрий зберігає значення винятку; це значення доступне лише в межах {{Glossary("Scope", "області видимості")}} блоку `catch`.

### Умовні блоки catch

"Умовні блоки `catch`" можна утворити шляхом комбінування блоків `try...catch` зі структурами `if...else if...else`, отак:

```js
try {
myroutine(); // може викинути три типи винятків
} catch (e) {
if (e instanceof TypeError) {
// інструкції для обробки винятків TypeError
} else if (e instanceof RangeError) {
// інструкції для обробки RangeError
} else if (e instanceof EvalError) {
// інструкції для обробки EvalError
} else {
// інструкції для обробки будь-яких непередбачених винятків
logMyErrors(e); // передати об'єкт винятку обробнику помилок
}
}
```

Поширена ситуація для застосування такого підходу – потреба перехопити (й заглушити) невелику підмножину очікуваних помилок, а потім повторно викинути помилку, якщо вона до такої підмножини не належить:

```js
try {
myRoutine();
} catch (e) {
if (e instanceof RangeError) {
// інструкції для обробки цієї дуже поширеної очікуваної помилки
} else {
throw e; // повторно викинути помилку без змін
}
}
```

### Ідентифікатор винятку

Коли в блоку `try` викидається виняток, `exception_var` (тобто `e` в `catch (e)`) зберігає значення винятку. Цей ідентифікатор можна використати для отримання інформації про викинутий виняток. Він доступний лише в {{Glossary("Scope", "області видимості ")}} блоку `catch`. Якщо значення винятку непотрібне, цей ідентифікатор можна опустити.

```js
function isValidJSON(text) {
try {
JSON.parse(text);
return true;
} catch {
return false;
}
}
```

### Блок finally

Блок `finally` містить інструкції, що будуть виконані після виконання блоку `try` та блоку (чи блоків) `catch`, але до інструкцій, що стоять після блоку `try...catch...finally`. Потік виконання обов'язково зайде до блоку `finally`, що може відбутися в один з наступних способів:

- Безпосередньо перед нормальним завершенням виконання блоку `try` (винятків викинуто не було);
- Безпосередньо перед нормальним завершенням виконання блоку `catch`;
- Безпосередньо перед виконанням інструкції контролю потоку виконання (`return`, `throw`, `break`, `continue`) в блоку `try` чи блоку `catch`.

Якщо виняток викидається з блоку `try`, то навіть якщо немає блоку `catch` для обробки винятку, блок `finally` все одно виконується, у випадку чого виняток все одно викидається негайно після закінчення виконання блоку `finally`.

Наступний приклад демонструє одну з ситуацій для використання блоку `finally`. Код відкриває файл, а потім виконує інструкції, що використовують цей файл; блок `finally` пересвідчується, що файл обов'язково закривається після використання, навіть якщо було викинуто виняток.

```js
openMyFile();
try {
// затягти ресурс
writeMyFile(theData);
} finally {
closeMyFile(); // завжди закривати ресурс
}
```

Інструкції контролю потоку виконання (`return`, `throw`, `break`, `continue`) в блоку `finally` будуть "приховувати" будь-яке підсумкове значення блоку `try` чи блоку `catch`. В прикладі нижче блок `try` пробує повернути 1, але перед поверненням контроль виконання спершу переходить до блоку `finally`, тож натомість повертається повернене значення блоку `finally`.

```js
function doIt() {
try {
return 1;
} finally {
return 2;
}
}

doIt(); // повертає 2
```

Загалом є недоброю ідеєю мати інструкції контролю потоку виконання в блоку `finally`. Його слід використовувати лише для коду очищення.

## Приклади

### Вкладені блоки try

По-перше, погляньмо, що станеться з цим:

```js
try {
try {
throw new Error('йой');
} finally {
console.log('finally');
}
} catch (ex) {
console.error('зовнішній', ex.message);
}

// Вивід:
// "finally"
// "зовнішній" "йой"
```

Тепер – якщо виняток перехоплений уже внутрішнім блоком `try`: додається блок `catch`:

```js
try {
try {
throw new Error('йой');
} catch (ex) {
console.error('внутрішній', ex.message);
} finally {
console.log('finally');
}
} catch (ex) {
console.error('зовнішній', ex.message);
}

// Вивід:
// "внутрішній" "йой"
// "finally"
```

А тепер – повторне викидання помилки.

```js
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

Якщо блок `finally` повертає значення, то таке значення стає поверненим значенням всієї інструкції `try-catch-finally`, незалежно від будь-яких інструкцій `return` в блоках `try` і `catch`. Так само це стосується винятків, викинутих зсередини блоку `catch`:

```js
(() => {
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`.

## Специфікації

{{Specifications}}

## Сумісність із браузерами

{{Compat}}

## Дивіться також

- {{jsxref("Error")}}
- {{jsxref("Statements/throw", "throw")}}