Skip to main content

Нова помилка всередині catch

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

Теорія

TL;DR

  • catch ловить лише те, що сталося в його власному блоці try.
  • Помилка з тіла catch іде вгору по стеку до наступного обробника.
  • Якщо зовнішнього обробника немає, отримуємо uncaught помилку і падіння програми.
  • finally виконується завжди, навіть коли catch кинув нову помилку.
  • Щоб обробити помилку локально, обгорніть тіло catch у власний try...catch.

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

javascript
try { throw new Error("failed in try"); } catch (err) { console.log("caught:", err.message); // a new error right here throw new Error("failed inside catch"); }

Вивід:

text
caught: failed in try Uncaught Error: failed inside catch

Першу помилку було спіймано, друга лишилася без обробника і поклала програму.

Що відбувається крок за кроком

  1. У try виникає помилка, керування переходить до catch.
  2. У catch починає виконуватися код обробки.
  3. Якщо всередині catch знову виникає помилка, поточний catch її вже не ловить: він відповідає тільки за помилки зі свого try.
  4. Нова помилка піднімається вгору по стеку, до найближчого зовнішнього try...catch, якщо він є.
  5. Якщо зовнішнього try...catch немає, програма завершується з помилкою.

Зовнішній try...catch ловить помилку з catch

Щоб обробити нову помилку, потрібна ще одна конструкція рівнем вище:

javascript
try { try { throw new Error("failed in try"); } catch (err) { console.log("inner catch:", err.message); throw new Error("failed in catch"); } } catch (err) { console.log("outer catch caught:", err.message); }

Вивід:

text
inner catch: failed in try outer catch caught: failed in catch

Тепер зовнішня конструкція спіймала помилку, яка сталася всередині блоку catch.

А ось що буде без зовнішнього обробника, помилка просто валить скрипт:

javascript
try { throw new Error("first failure"); } catch (e) { console.log("catch:", e.message); JSON.parse("invalid json"); // SyntaxError }

Вивід:

text
catch: first failure Uncaught SyntaxError: Unexpected token 'i', "invalid json" is not valid JSON

finally виконується в будь-якому разі

Навіть якщо в catch виникла нова помилка, блок finally все одно відпрацює, перш ніж помилка спливе назовні.

javascript
try { try { throw new Error("failed in try"); } catch (e) { console.log("catch:", e.message); throw new Error("failed in catch"); } finally { console.log("finally: always runs"); } } catch (e) { console.log("outer catch:", e.message); }

Вивід:

text
catch: failed in try finally: always runs outer catch: failed in catch

Порядок важливий: спершу finally, і лише потім помилка потрапляє до зовнішнього catch.

Вкладений try усередині catch

Ще один спосіб, обгорнути тіло catch у власний try...catch:

javascript
try { throw new Error("failed in try"); } catch (e) { try { console.log("catch:", e.message); throw new Error("failed inside catch"); } catch (innerErr) { console.log("caught the inner one:", innerErr.message); } }

Вивід:

text
catch: failed in try caught the inner one: failed inside catch

Так помилки всередині catch теж лишаються під контролем і нікуди не спливають.

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

СценарійЩо відбувається
Помилка в catchПоточний catch її не ловить
Є зовнішній try...catchПомилка передається туди
Немає зовнішнього catchПрограма падає
Є finallyВін усе одно виконується
Тіло catch обгорнуте у свій tryВнутрішня помилка ловиться локально

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

  • Вважати, що catch перехопить власний throw. Обробник уже активний і сам себе не ловить.
  • Забувати, що після throw у catch решта тіла catch не виконається.
  • Думати, що нова помилка в catch скасовує finally. finally виконується завжди.
  • Кидати нову помилку і губити початкову причину. Передавайте її далі: throw new Error("wrapper", { cause: err }).
  • Кидати помилку з finally. Такий throw перекриває виняток, що вже летів назовні, і початкова помилка зникає безслідно.

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

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

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