← Назад к вопросам
Как использовать try catch в Async/await?
1.0 Junior🔥 122 комментариев
#JavaScript Core
Комментарии (2)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Try/Catch в Async/Await
Это фундаментальный паттерн обработки ошибок в асинхронном коде. Давай разберемся, как правильно ловить ошибки.
Базовый синтаксис
async function fetchUser(id) {
try {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const user = await response.json();
return user;
} catch (error) {
console.error("Ошибка загрузки пользователя:", error.message);
return null;
}
}
Как это работает:
tryблок выполняется- Если где-то выбросится ошибка (throw или отклоненный Promise) — прыгаем в
catch - В
catchобрабатываем ошибку finallyвыполняется в любом случае (опционально)
Реальный пример: загрузка данных
async function loadUserProfile(userId) {
try {
// Загружаем пользователя
const userRes = await fetch(`/api/users/${userId}`);
if (!userRes.ok) throw new Error("Пользователь не найден");
const user = await userRes.json();
// Загружаем его посты
const postsRes = await fetch(`/api/users/${userId}/posts`);
if (!postsRes.ok) throw new Error("Посты не найдены");
const posts = await postsRes.json();
return { user, posts };
} catch (error) {
console.error("Ошибка:", error.message);
throw error; // Пробросим выше
}
}
Различные типы ошибок
В catch блоке может быть разная информация:
async function operation() {
try {
await fetch("/api/data");
} catch (error) {
// error может быть разного типа
if (error instanceof TypeError) {
// Ошибка сети или синтаксиса
console.log("Сетевая ошибка");
} else if (error instanceof SyntaxError) {
// JSON невалидный
console.log("Невалидный JSON");
} else if (error.name === "AbortError") {
// Запрос отменили
console.log("Запрос отменен");
} else {
// Какая-то другая ошибка
console.log("Неизвестная ошибка");
}
}
}
Finally блок
Это выполняется в любом случае — пригодится для очистки:
async function fetchWithTimeout(url, timeout = 5000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, { signal: controller.signal });
return await response.json();
} catch (error) {
console.error("Ошибка:", error.message);
} finally {
// Очищаем таймер в любом случае
clearTimeout(timeoutId);
}
}
Обработка нескольких операций
Последовательно (одна за другой):
async function processUser(userId) {
try {
const user = await fetchUser(userId);
const settings = await fetchSettings(userId);
const notifications = await fetchNotifications(userId);
return { user, settings, notifications };
} catch (error) {
console.error("Ошибка:", error);
// Если любая операция упадет — все дальше не выполняются
}
}
Параллельно (всё сразу):
async function processUser(userId) {
try {
// Promise.all бросит ошибку если хоть одна упадет
const [user, settings, notifications] = await Promise.all([
fetchUser(userId),
fetchSettings(userId),
fetchNotifications(userId)
]);
return { user, settings, notifications };
} catch (error) {
console.error("Ошибка:", error);
}
}
Параллельно, но с частичной обработкой ошибок:
async function processUser(userId) {
const results = await Promise.allSettled([
fetchUser(userId),
fetchSettings(userId),
fetchNotifications(userId)
]);
// Каждый результат может быть fulfilled или rejected
const [userResult, settingsResult, notificationsResult] = results;
const data = {};
if (userResult.status === "fulfilled") {
data.user = userResult.value;
} else {
console.error("Ошибка загрузки пользователя:", userResult.reason);
}
// Аналогично для других
return data;
}
Пример в React
function UserPage({ userId }) {
const [user, setUser] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
let isMounted = true; // Для предотвращения утечек памяти
async function loadUser() {
try {
setLoading(true);
setError(null);
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
if (isMounted) {
setUser(data);
}
} catch (err) {
if (isMounted) {
setError(err.message);
}
} finally {
if (isMounted) {
setLoading(false);
}
}
}
loadUser();
return () => {
isMounted = false; // Cleanup
};
}, [userId]);
if (loading) return <div>Загружается...</div>;
if (error) return <div>Ошибка: {error}</div>;
return <div>{user.name}</div>;
}
Кастомная обработка ошибок
class ApiError extends Error {
constructor(statusCode, message) {
super(message);
this.statusCode = statusCode;
}
}
async function apiCall(url, options = {}) {
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new ApiError(
response.status,
await response.text()
);
}
return await response.json();
} catch (error) {
if (error instanceof ApiError) {
// Обрабатываем HTTP ошибки
if (error.statusCode === 401) {
// Перенаправить на логин
} else if (error.statusCode === 403) {
// Показать "Доступ запрещен"
}
} else if (error instanceof TypeError) {
// Сетевая ошибка
console.error("Нет интернета");
}
throw error; // Пробросим выше
}
}
Retry логика
async function fetchWithRetry(url, maxAttempts = 3) {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return await response.json();
} catch (error) {
if (attempt === maxAttempts) {
throw error; // Последняя попытка, бросим ошибку
}
// Ждем перед следующей попыткой
const delay = Math.pow(2, attempt - 1) * 1000; // 1s, 2s, 4s...
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
Лучшие практики
- Всегда обрабатывай ошибки, не оставляй Promise отклоненными
- Проверяй HTTP статусы — fetch не бросает ошибку при 404 или 500
- Используй finally для очистки — таймауты, соединения, подписки
- Пробрасывай ошибки выше если необходимо — не поглощай их просто так
- В React — проверяй isMounted перед setState в asyn функциях
- Логируй детали ошибок для отладки, но не содержимое в production
- Используй Promise.allSettled для параллельных операций где нужна частичная обработка
Try/catch с async/await — это самый читаемый способ обработки ошибок в JavaScript.