Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Нова помилка всередині catch». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Блок `catch` не ловить власні помилки: усе, що кинуто всередині нього, летить далі вгору по стеку викликів.** Такий виняток шукає найближчий зовнішній `try...catch`, і якщо його немає, програма падає з неопрацьованою помилкою. Блок `finally` при цьому все одно відпрацює, перш ніж помилка спливе назовні. ```javascript try { throw new Error("failed in try"); } catch (err) { console.log("caught:", err.message); throw new Error("failed inside catch"); // nobody here catches this } ``` **Ключове:** `catch` обробляє лише помилки з власного `try`; щоб перехопити помилку із самого `catch`, потрібен зовнішній `try...catch` або вкладений `try` у тілі `catch`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Помилка, кинута всередині `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` перекриває виняток, що вже летів назовні, і початкова помилка зникає безслідно.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.