Помилки в async функціях
1. Основний принцип
Помилки всередині
async-функцій автоматично перетворюються на відхилений проміс (Promise.reject).Тому для їх обробки використовується або:
- конструкція
try...catch,- або метод
.catch()у поверненого промісу.
2. Приклад з try...catch (основний спосіб)
async function getData() {
try {
const res = await fetch("https://no-such-domain.com");
const data = await res.json();
console.log(data);
} catch (error) {
console.error("Сталася помилка:", error.message);
}
}
getData();Вивід:
Сталася помилка: fetch failedТут try...catch працює аналогічно синхронному коду,
але ловить помилки з усіх await всередині.
3. Чому це працює
await "зупиняє" виконання функції, поки проміс не завершиться.
Якщо проміс відхилений (reject), await генерує виняток,
і керування передається в catch.
Приклад:
async function example() {
const result = await Promise.reject("Помилка!");
console.log(result); // не виконається
}
example().catch(console.error);Вивід:
Помилка!4. Помилка без try...catch -> проміс відхиляється
Якщо не обгорнути await у try...catch,
функція просто поверне відхилений проміс,
який можна обробити через .catch():
async function fail() {
throw new Error("Щось пішло не так");
}
fail().catch(err => console.error("Спіймали:", err.message));Вивід:
Спіймали: Щось пішло не такЦе еквівалентно обробці .catch() у звичайних промісах.
5. Кілька await - одна зона try
Ти можеш обгортати декілька await в один try,
якщо хочеш обробити всі помилки одним способом:
async function loadUserData() {
try {
const user = await fetch("/api/user");
const posts = await fetch("/api/posts");
const comments = await fetch("/api/comments");
} catch (e) {
console.error("Помилка при завантаженні даних:", e);
}
}Якщо будь-яка з операцій впаде - керування одразу перейде в catch.
6. Локальний try для точкового контролю
Іноді краще обгортати окремі await, якщо ти хочеш обробляти помилки по-різному:
async function example() {
try {
const user = await fetchUser();
} catch (e) {
console.error("Помилка при завантаженні користувача:", e);
}
try {
const posts = await fetchPosts();
} catch (e) {
console.error("Помилка при завантаженні постів:", e);
}
}7. Приклад: "зцілення" помилки (аналог .catch().then())
Якщо в catch повернути значення - функція продовжить виконуватися далі:
async function example() {
try {
await Promise.reject("Помилка!");
} catch (e) {
console.log("Спіймали:", e);
return "Значення за умовчанням";
}
}
example().then(result => console.log("Результат:", result));Вивід:
Спіймали: Помилка!
Результат: Значення за умовчанням8. Помилки в паралельних await (Promise.all)
Якщо ти виконуєш кілька await паралельно через Promise.all,
і хоча б один з промісів відхилиться - весь Promise.all впаде.
async function parallel() {
try {
const [a, b] = await Promise.all([
Promise.resolve("ok"),
Promise.reject("помилка"),
]);
} catch (e) {
console.log("Спіймали:", e);
}
}
parallel();Вивід:
Спіймали: помилка9. Використання catch напряму (альтернатива try...catch)
async function getUser() {
const res = await fetch("/api/user").catch(err => {
console.error("Помилка при запиті:", err);
return null; // повернемо безпечне значення
});
console.log("Результат:", res);
}
getUser();Цей спосіб часто застосовують, якщо потрібно просто "придушити" помилку і продовжити виконання програми.
10. Найкращі практики
| Ситуація | Що використовувати |
|---|---|
| Обробка помилок в одній функції | try...catch |
| Обробка помилок при виклику async-функції | .catch() |
| Різні типи помилок з різними реакціями | Кілька try...catch |
Кілька паралельних await | Promise.allSettled() замість Promise.all |
| Логування і прокидання далі | catch (e) { log(e); throw e; } |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.