1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
|
---
title: try...catch
slug: Web/JavaScript/Reference/Statements/try...catch
tags:
- Error
- JavaScript
- виняток
- помилка
translation_of: Web/JavaScript/Reference/Statements/try...catch
---
<div>{{jsSidebar("Statements")}}</div>
<p>Конструкція <strong><code>try...catch</code></strong> позначає блок команд, які треба виконати, та визначає реакцію в разі, якщо буде викинуто виняток.</p>
<div>{{EmbedInteractiveExample("pages/js/statement-trycatch.html")}}</div>
<h2 id="Синтаксис">Синтаксис</h2>
<pre class="syntaxbox">try {
<em>try_statements</em>
}
[catch (<em>exception_var_1</em> if <em>condition_1</em>) { // нестандартна форма
<em>catch_statements_1</em>
}]
...
[catch (<em>exception_var_2</em>) {
<em>catch_statements_2</em>
}]
[finally {
<em>finally_statements</em>
}]
</pre>
<dl>
<dt><code>try_statements</code></dt>
<dd>Команди, які треба виконати.</dd>
</dl>
<dl>
<dt><code>catch_statements_1</code>, <code>catch_statements_2</code></dt>
<dd>Команди, що виконуються, якщо викинуто виняток у блоці <code>try</code>.</dd>
</dl>
<dl>
<dt><code>exception_var_1</code>, <code>exception_var_2</code></dt>
<dd>Ідентифікатор, що містить об'єкт винятку для відповідного блоку <code>catch</code>.</dd>
</dl>
<dl>
<dt><code>condition_1</code></dt>
<dd>Умовний вираз.</dd>
</dl>
<dl>
<dt><code>finally_statements</code></dt>
<dd>Команди, що виконуються після завершення блоку <code>try</code>. Ці команди виконуються незалежно від того, чи було викинуто або перехоплено виняток.</dd>
</dl>
<h2 id="Опис">Опис</h2>
<p>Вираз <code>try</code> містить одну або більше команд у блоці <code>try</code>. Фігурні дужки <code>{}</code> є обов'язковими, навіть для однієї команди. Має бути присутній принаймні один блок <code>catch</code> або <code>finally</code>. Це утворює три можливі форми виразу <code>try</code>:</p>
<ol>
<li><code>try...catch</code></li>
<li><code>try...finally</code></li>
<li><code>try...catch...finally</code></li>
</ol>
<p>Блок <code>catch</code> містить команди, які визначають, що робити, якщо викинуто виняток у блоці <code>try</code>. Отже, ви хочете, щоб блок <code>try</code> виконався успішно, а в разі неуспіху ви хочете передати контроль до блоку <code>catch</code>. В разі, якщо будь-який вираз всередині блоку <code>try</code> (або функція, викликана зсередини блоку <code>try</code>) викидає виняток, контроль негайно переходить до блоку <code>catch</code>. Якщо жодних винятків у блоці <code>try</code> не було викинуто, блок <code>catch</code> пропускається.</p>
<p>Блок <code>finally</code> виконується після виконання блоків <code>try</code> та <code>catch</code>, але до команд, що йдуть після виразу <code>try</code>. Він завжди виконується, незалежно від того, чи було викинуто або перехоплено виняток.</p>
<p>Ви можете створити один або більше вкладених виразів <code>try</code>. Якщо внутрішній <code>try</code> не має блоку <code>catch</code>, контроль передається у блок <code>catch</code> зовнішнього <code>try</code>.</p>
<p>Ви також можете використовувати <code>try</code>, щоб обробляти винятки JavaScript. Ви знайдете більше інформації щодо винятків JavaScript у <a href="/uk/docs/Web/JavaScript/Guide" title="en/JavaScript/Guide">Посібнику JavaScript</a>.</p>
<h3 id="Безумовний_catch">Безумовний <code>catch</code></h3>
<p>Коли використовується один безумовний блок <code>catch</code>, перехід у <code>catch</code> відбувається у випадку викидання будь-якого винятку. Наприклад, коли виняток стається у наступному коді, контроль передається до блоку <code>catch</code>.</p>
<pre class="brush: js">try {
throw 'myException'; // генерує виняток
}
catch (e) {
// команди обробки будь-яких винятків
logMyErrors(e); // передає об'єкт винятку до обробника помилок
}
</pre>
<p>Блок <code>catch</code> вказує ідентифікатор (<code>e</code> у наведеному прикладі), який містить значення, визначене у операторі <code>throw</code>. Блок <code>catch</code> унікальний тим, що JavaScript створює цей ідентифікатор при вході у блок <code>catch</code>, а також додає його у область видимості; ідентифікатор "живе" тільки протягом виконання блоку <code>catch</code>; коли <code>catch</code> завершується, ідентифікатор більше недоступний.</p>
<h3 id="Умовний_блок_catch">Умовний блок <code>catch</code></h3>
<p>{{non-standard_header}}</p>
<p>Ви також можете використати один або декілька умовних блоків <code>catch</code> для обробки специфічних винятків. В цьому випадку вхід у відповідний блок <code>catch</code> відбувається, коли викидається вказаний виняток. У наступному прикладі код у блоці <code>try</code> може викинути один з трьох винятків: {{jsxref("TypeError")}}, {{jsxref("RangeError")}} або {{jsxref("EvalError")}}. Коли виникає виняток, контроль передається до відповідного блоку <code>catch</code>. Якщо виняток не є одним із вказаних, і був знайдений безумовний блок <code>catch</code>, контроль передається до цього блоку <code>catch</code>.</p>
<p>Якщо ви використовуєте безумовний <code>catch</code> з одним або кількома умовними блоками <code>catch</code>, безумовний <code>catch</code> має бути вказаний останнім. Інакше безумовний <code>catch</code> перехоплюватиме всі види винятків до того, як вони потраплять в умовні блоки.</p>
<p>Нагадування: ця функціональність не є частиною специфікації ECMAScript і ніколи не прибиралася з Firefox 59. Вона більше не підтримується у жодних сучасних веб-переглядачах.</p>
<pre class="brush: js">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); // передати об'єкт винятку до обробника помилок
}
</pre>
<p>Ось такі ж "Умовні блоки catch", написані кодом, що відповідає специфікації ECMAScript (він доволі багатослівний, зате працює всюди):</p>
<pre class="brush: 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); // передати об'єкт винятку до обробника помилок
}
}
</pre>
<h3 id="Ідентифікатор_винятку">Ідентифікатор винятку</h3>
<p>Коли викидається виняток у блоці <code>try</code>, ідентифікатор <em><code>exception_var</code></em> (наприклад, <code>e</code> у <code>catch (e)</code>) містить значення, вказане у виразі <code>throw</code>. Ви можете скористатись цим ідентифікатором, щоб отримати інформацію про виняток. Це локальний ідентифікатор блоку <code>catch</code>. Тобто, він створюється при вході у <code>catch</code>, а після того, як виконання блоку <code>catch</code> завершується, ідентифікатор більше недоступний.</p>
<pre class="brush: js">function isValidJSON(text) {
try {
JSON.parse(text);
return true;
} catch {
return false;
}
}
</pre>
<h3 id="Блок_finally">Блок <code>finally</code></h3>
<p>Блок <code>finally</code> містить команди, які виконуються після виконання блоків <code>try</code> та <code>catch</code>, але до команд, що розташовані після конструкції <code>try...catch...finally</code>. Зверніть увагу, що <code>finally</code> виконується незалежно від того, чи був викинутий виняток. Також, якщо виняток було викинуто, команди блоку <code>finally</code> виконуються навіть якщо немає блоку <code>catch</code>, щоб обробити виняток.</p>
<p>Ви можете скористатись блоком <code>finally</code>, щоб у разі викидання винятку ваш скрипт переривався красиво; наприклад, вам може знадобитися звільнити ресурс, до якого був прив'язаний ваш скрипт.</p>
<p>Це може виглядати дивним, мати спеціальний блок, пов'язаний з винятками, що виконується <em>незалежно</em> від того, чи стався виняток, але ця конструкція насправді виконує свою задачу. Важливим моментом є те, що блок <code>finally</code> виконується завжди, на відміну від звичайного коду, розташованого після <code>try...catch</code>.</p>
<p>Наприклад, якщо станеться інший виняток всередині <code>catch</code> цього <code>try</code>, будь-який код, що не був виконаний у зовнішньому <code>try</code>, що замикає цей <code>try...catch</code> (або у головному потоці, якщо виконувався не зовнішній <code>try</code>), не буде виконаний, оскільки контроль негайно перейде до блоку <code>catch</code> зовнішнього <code>try</code> (або до внутнішнього генератора помилок, якщо виконується не блок <code>try</code>).</p>
<p>Таким чином, будь який поточний код очистки, що виконується у цій зовнішній (або головній) секції перед закінченням, буде пропущений. Однак, якщо вираз <code>try</code> містить блок <code>finally</code>, то спочатку буде виконаний код блоку <code>finally</code>, дозволяючи зробити очистку, і тільки ПОТІМ контроль буде передано до блоку <code>catch</code> іншого <code>try</code> (або до генератора помилок) для обробки винятку.</p>
<p>Отже, якщо поточна очистка повинна бути зроблена, не зважаючи на те, чи успішно виконаний код у <code>try...catch</code>, тоді, якби блок <code>finally</code> виконувався тільки після винятку, той самий код очистки довелося б повторювати і всередині, і поза блоком <code>finally</code>, і, таким чином, немає причини не мати один лише блок <code>finally</code>, який виконується незалежно від того, стався виняток чи ні.</p>
<p>Наступний приклад відкриває файл і далі виконує команди, які використовують цей файл (JavaScript на стороні сервера дозволяє звертатись до файлів). Якщо викидається виняток, доки файл відкритий, блок <code>finally</code> закриває цей файл до того, як скрипт переривається. Код у блоці <code>finally</code> також виконується з явним поверненням з блоку <code>try</code> або <code>catch</code>.</p>
<pre class="brush: js">openMyFile();
try {
// прив'язати ресурс
writeMyFile(theData);
}
finally {
closeMyFile(); // завжди закривати ресурс
}
</pre>
<h2 id="Приклади">Приклади</h2>
<h3 id="Вкладені_блоки_try">Вкладені блоки try</h3>
<p>Спочатку подивимось, що відбувається тут:</p>
<pre class="brush: js">try {
try {
throw new Error('ой-ой');
}
finally {
console.log('finally');
}
}
catch (ex) {
console.error('зовнішній', ex.message);
}
// Результат:
// "finally"
// "зовнішній" "ой-ой"
</pre>
<p>Тепер, якщо ми вже перехопили виняток у внутрішньому try, додавши блок catch.</p>
<pre class="brush: js">try {
try {
throw new Error('ой-ой');
}
catch (ex) {
console.error('внутрішній', ex.message);
}
finally {
console.log('finally');
}
}
catch (ex) {
console.error('зовнішній', ex.message);
}
// Результат:
// "внутрішній" "ой-ой"
// "finally"
</pre>
<p>А тепер викинемо цю помилку повторно.</p>
<pre class="brush: 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"
// "зовнішній" "ой-ой"
</pre>
<p>Будь-який виняток буде перехоплений лише один раз найближчим замикаючим блоком catch, якщо тільки він не був викинутий повторно. Звісно, будь-які нові винятки, викинуті у "внутрішньому" блоці (бо код у блоці catch може зробити те, що викине помилку), будуть перехоплені "зовнішнім" блоком.</p>
<h3 id="Повернення_значень_з_блоку_finally">Повернення значень з блоку finally</h3>
<p>Якщо блок <code>finally</code> повертає значення, це значення повертається усією конструкцією <code>try-catch-finally</code>, не зважаючи на будь-які інші оператори <code>return</code> у блоках <code>try</code> та <code>catch</code>. Це стосується й винятків, викинутих всередині блоку catch:</p>
<pre class="brush: js">(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"</pre>
<p>Зовнішній "ой-ой" не викидається через return у блоці finally. Те саме стосувалося б будь-якого значення, що поверталося б з блоку catch.</p>
<h2 id="Специфікації">Специфікації</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Специфікація</th>
<th scope="col">Статус</th>
<th scope="col">Коментар</th>
</tr>
<tr>
<td>{{SpecName('ES3')}}</td>
<td>{{Spec2('ES3')}}</td>
<td>Початкове визначення. Реалізоване у JavaScript 1.4</td>
</tr>
<tr>
<td>{{SpecName('ES5.1', '#sec-12.14', 'try statement')}}</td>
<td>{{Spec2('ES5.1')}}</td>
<td></td>
</tr>
<tr>
<td>{{SpecName('ES6', '#sec-try-statement', 'try statement')}}</td>
<td>{{Spec2('ES6')}}</td>
<td></td>
</tr>
<tr>
<td>{{SpecName('ESDraft', '#sec-try-statement', 'try statement')}}</td>
<td>{{Spec2('ESDraft')}}</td>
<td>Не є частиною нинішнього стандарту ECMA-262: Використання кількох блоків catch та умовні блоки (розширення SpiderMonkey, JavaScript 1.5).</td>
</tr>
</tbody>
</table>
<h2 id="Сумісність_з_веб-переглядачами">Сумісність з веб-переглядачами</h2>
<p>{{Compat("javascript.statements.try_catch")}}</p>
<h2 id="Див._також">Див. також</h2>
<ul>
<li>{{jsxref("Error")}}</li>
<li>{{jsxref("Statements/throw", "throw")}}</li>
</ul>
|