Skip to main content

Помилки в async

Головне правило

Будь-яка async-функція завжди повертає проміс. Якщо всередині неї викидається помилка (throw), то проміс переходить у стан rejected.

Отже, помилки можна обробляти двома способами:

  1. через try...catch усередині самої функції;
  2. через .catch() зовні при виклику.

1. Обробка через try...catch (усередині функції)

Це найзрозуміліший і найзвичніший спосіб - схожий на синхронний код.

javascript
async function getData() { try { const res = await fetch('https://api.github.com/404'); // помилка мережі const data = await res.json(); console.log('Отримано:', data); } catch (error) { console.error('Помилка всередині async:', error.message); } } getData();

Вивід:

javascript
Помилка всередині async: Failed to fetch

try...catch "ловить":

  • помилки, викинуті через throw;
  • відхилені проміси, на яких стоїть await.

Як це працює

await під капотом робить try { ... } catch { ... } для промісу, який може завершитися з помилкою (reject).

javascript
const result = await Promise.reject('помилка'); // викине виняток → перейде в блок catch

2. Обробка через .catch() (зовні функції)

Оскільки async-функція повертає Promise, помилку можна обробити звичайним методом .catch():

javascript
async function getUser() { const res = await fetch('https://wrong.url'); return res.json(); } getUser() .then(console.log) .catch(err => console.error('Помилка зовні:', err.message));

Вивід:

javascript
Помилка зовні: Failed to fetch

Відмінність від try...catch: тут помилка обробляється при виклику, а не всередині функції.


3. Приклад з ручним throw

javascript
async function example() { const data = await Promise.resolve('OK'); if (!data) throw new Error('Немає даних!'); return data; } example() .then(console.log) .catch(err => console.error(err.message));

Вивід:

javascript
OK

Якщо умова спрацює, throw перетвориться на Promise.reject().


4. Комбінація try...catch + повторний throw

Іноді потрібно обробити помилку частково, але передати її далі - наприклад, щоб залогувати.

javascript
async function processData() { try { const res = await fetch('https://wrong.url'); return await res.json(); } catch (err) { console.error('Помилка запиту:', err.message); throw new Error('Помилка при обробці даних'); } } processData().catch(err => console.error('Фінальна помилка:', err.message));

Вивід:

javascript
Помилка запиту: Failed to fetch Фінальна помилка: Помилка при обробці даних

5. Обробка кількох помилок підряд

Можна використовувати кілька try...catch для різних етапів:

javascript
async function pipeline() { try { const res = await fetch('/api/data'); try { const data = await res.json(); console.log('Дані:', data); } catch (err) { console.error('Помилка парсингу JSON:', err.message); } } catch (err) { console.error('Помилка запиту:', err.message); } }

Такий підхід корисний, коли потрібно обробити різні рівні помилок окремо.


6. Обробка без try...catch (через утиліту)

Іноді зручніше використовувати допоміжну функцію:

javascript
const to = (promise) => promise.then(data => [null, data]).catch(err => [err]); async function run() { const [err, data] = await to(fetch('/api/user').then(r => r.json())); if (err) return console.error('Помилка:', err.message); console.log(data); }

Такий патерн часто використовують у Node.js, щоб не писати try...catch на кожному кроці.


7. Глобальне перехоплення необроблених помилок

Якщо забули .catch() або try...catch, помилку можна перехопити глобально:

javascript
window.addEventListener('unhandledrejection', (event) => { console.error('Необроблений проміс:', event.reason); });

Це аналог try...catch для всіх промісів, у яких немає .catch().


Проста аналогія

Уяви async-функцію як квест.

  • await - це "завдання", яке може провалитися;
  • try...catch - це "страховка": якщо провал - ти ловиш помилку і вирішуєш, що робити;
  • .catch() зовні - це "гейм-майстер", який ловить фатальні помилки, якщо гравець не впорався.

ПІДСУМОК

СпосібДе ловить помилкуПриклад
try...catchусередині async-функціїtry { await ... } catch (e) { ... }
.catch()при виклику функціїmyAsync().catch(e => ...)
Глобальне перехопленнядля всіх необробленихwindow.addEventListener('unhandledrejection', ...)
Патерн [err, data]через обгорткуconst [err, res] = await to(promise)

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

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

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