Skip to main content

Коли виконується блок catch

catch виконується тільки тоді, коли в блоці try виникло виключення. Помилку могли кинути вручну через throw або її згенерував сам движок, наприклад ReferenceError чи TypeError. Якщо try відпрацював чисто, блок catch пропускається, наче його немає.

Теорія

TL;DR

  • catch спрацьовує рівно за однієї умови: усередині його try кинуто виключення.
  • Джерело помилки не має значення: ручний throw і автоматична помилка движка обробляються однаково.
  • Помилка обриває try на місці, наступні рядки блоку не виконуються.
  • В catch(error) доступний об'єкт помилки з name, message і stack.
  • Помилка поза блоком try не перехоплюється.
  • Асинхронна помилка з колбека або з promise без await теж не перехоплюється.
  • Якщо помилок могло бути кілька, обробляється перша: до другої виконання не дійде.

Швидкий приклад

javascript
try { console.log("Початок"); throw new Error("Сталася помилка!"); console.log("Цей код не виконається"); } catch (error) { console.log("Спіймали:", error.message); }

Вивід:

text
Початок Спіймали: Сталася помилка!

Покроковий механізм

  1. Код усередині try { ... } починає виконуватися рядок за рядком.
  2. Якщо помилок немає, catch не викликається взагалі.
  3. Якщо всередині try сталася помилка, виконання try негайно обривається і керування переходить у catch.
  4. У catch (error) доступний об'єкт помилки, який можна обробити, залогувати або кинути далі.

Коли catch спрацьовує

Приклад 1. Помилки немає, тому catch не спрацьовує:

javascript
try { console.log("Усе працює чудово!"); } catch (error) { console.log("Спіймали помилку:", error.message); } console.log("Продовжуємо виконання...");

Вивід:

text
Усе працює чудово! Продовжуємо виконання...

Приклад 2. Автоматична помилка движка:

javascript
try { console.log(a); // ReferenceError: a is not defined } catch (error) { console.log("Спіймали:", error.name); // ReferenceError }

catch спрацьовує тому, що JavaScript сам кинув виключення під час звернення до неоголошеної змінної.

Приклад 3. Помилка обриває try посередині:

javascript
try { console.log("1"); JSON.parse("not valid json"); // помилка тут console.log("2"); // не виконається } catch (error) { console.log("Спіймали:", error.message); } console.log("3");

Вивід:

text
1 Спіймали: Unexpected token 'o', "not valid json" is not valid JSON 3

Приклад 4. Якщо помилок кілька, обробляється перша:

javascript
try { throw new Error("Помилка 1"); throw new Error("Помилка 2"); // не виконається } catch (err) { console.log("Спіймано:", err.message); }

Вивід:

text
Спіймано: Помилка 1

Коли catch не спрацьовує

Помилка, що сталася поза блоком try, не має жодного стосунку до цього catch:

javascript
try { console.log("Усередині try все добре"); } catch (error) { console.log("Спіймали помилку:", error.message); } throw new Error("Помилка поза try!"); // не буде перехоплена

Скрипт впаде з неперехопленою помилкою, бо вона виникла після того, як конструкція вже завершилася.

Асинхронний код

try...catch не ловить помилки всередині колбеків і promise, якщо не використати await або .catch().

javascript
try { setTimeout(() => { throw new Error("Помилка в колбеку"); // не буде спіймана }, 1000); } catch (e) { console.log("Спіймано:", e.message); }

Виклик setTimeout завершується миттєво і без помилки, а сам колбек виконується пізніше, коли блок try уже закрито. Щоб перехоплювати помилки з promise, потрібен async/await або .catch():

javascript
async function run() { try { await Promise.reject(new Error("Помилка в promise")); } catch (e) { console.log("Спіймали:", e.message); } } run();

Підсумкова таблиця

СитуаціяЧи виконається catchПричина
У try немає помилокНіКод відпрацював нормально
У try виконано throwТакВиключення кинуто всередині блоку
JavaScript сам кинув помилку (ReferenceError тощо)ТакАвтоматична помилка часу виконання
Помилка поза tryНіНе входить в область обробки
Помилка в колбеку або promise без awaitНіАсинхронний код виконується поза блоком try

Типові помилки

  • Думати, що catch спрацьовує «на будь-яку помилку в програмі». Він бачить лише свій блок try і виклики, що йдуть з нього синхронно.
  • Загортати setTimeout або addEventListener у try і чекати перехоплення. Обробляти треба всередині самого колбека.
  • Забувати await перед асинхронним викликом. Без нього функція лише повертає promise, а відхилення стане unhandled rejection повз catch.
  • Розраховувати, що після помилки виконається решта try. Виконання обривається на рядку з помилкою, і жодний наступний рядок блоку не запуститься.
  • Мовчазний catch без логування. Помилка зникає, а баг лишається, і знайти його стає значно важче.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.