Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Коли виконується блок catch». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Блок `catch` виконується лише тоді, коли всередині відповідного блоку `try` виникло виключення: або кинуте вручну через `throw`, або згенероване самим движком (`ReferenceError`, `TypeError`, `SyntaxError` від `JSON.parse` тощо).** Якщо код у `try` відпрацював без помилок, `catch` просто пропускається. Щойно помилка сталася, решта рядків `try` не виконується, а керування одразу переходить у `catch`, куди передається об'єкт помилки. ```javascript try { console.log(a); // ReferenceError: a is not defined } catch (error) { console.log("Спіймали:", error.name); // ReferenceError } ``` **Ключове:** `catch` бачить лише синхронні помилки свого власного блоку `try`, тому виняток з колбека `setTimeout` або з promise без `await` він не перехопить.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`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` без логування.** Помилка зникає, а баг лишається, і знайти його стає значно важче.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.