Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Обработка ошибок в Promises
Да, можно и нужно ловить ошибки в Promise. Есть несколько способов, и каждый используется в зависимости от ситуации.
1. Метод .catch()
Классический способ - добавить обработчик ошибки через .catch():
Promise.resolve()
.then(() => {
throw new Error('Произошла ошибка!');
})
.catch((error) => {
console.error('Поймали ошибку:', error.message);
});
// Или с реальным запросом
fetch('/api/data')
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then((data) => {
console.log('Данные получены:', data);
})
.catch((error) => {
console.error('Ошибка:', error.message);
});
2. try/catch с async/await
Модернизированный способ, который читать проще:
async function fetchData() {
try {
const response = await fetch('/api/data');
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
console.log('Данные:', data);
return data;
} catch (error) {
console.error('Ошибка при загрузке:', error);
// Можно пробросить ошибку дальше
throw error;
}
}
3. Цепочка .catch() обработчиков
Можно ловить разные типы ошибок на разных уровнях:
Promise.resolve()
.then(() => fetchUser())
.catch((error) => {
console.error('Ошибка при получении пользователя:', error);
// Можем вернуть значение по умолчанию
return { id: 0, name: 'Guest' };
})
.then((user) => fetchUserPosts(user.id))
.catch((error) => {
console.error('Ошибка при получении постов:', error);
return [];
})
.then((posts) => {
console.log('Всё готово, посты:', posts);
});
4. Promise.all() с обработкой ошибок
Когда выполняешь несколько промисов одновременно:
// Если хотя бы один Promise отклонится, весь Promise.all() падает
Promise.all([
fetch('/api/users').then(r => r.json()),
fetch('/api/posts').then(r => r.json()),
fetch('/api/comments').then(r => r.json())
])
.then(([users, posts, comments]) => {
console.log('Все данные загружены');
})
.catch((error) => {
console.error('Одна из запросов не удалась:', error);
});
// Или с async/await
async function loadAllData() {
try {
const [users, posts, comments] = await Promise.all([
fetch('/api/users').then(r => r.json()),
fetch('/api/posts').then(r => r.json()),
fetch('/api/comments').then(r => r.json())
]);
return { users, posts, comments };
} catch (error) {
console.error('Ошибка при загрузке данных:', error);
throw error;
}
}
5. Promise.allSettled() - продолжить при ошибках
Если нужно выполнить все промисы, даже если некоторые упадут:
const promises = [
fetch('/api/users').then(r => r.json()),
fetch('/api/posts').then(r => r.json()),
fetch('/api/broken').then(r => r.json()) // Эта упадёт
];
Promise.allSettled(promises)
.then((results) => {
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`Запрос ${index} успешен:`, result.value);
} else {
console.error(`Запрос ${index} упал:`, result.reason);
}
});
});
// Вывод:
// Запрос 0 успешен: {users...}
// Запрос 1 успешен: {posts...}
// Запрос 2 упал: Error: 404 Not Found
6. finally() - очистка ресурсов
Выполняется в любом случае, успешно или с ошибкой:
let isLoading = true;
fetch('/api/data')
.then((response) => response.json())
.then((data) => {
console.log('Данные:', data);
})
.catch((error) => {
console.error('Ошибка:', error);
})
.finally(() => {
isLoading = false;
console.log('Загрузка завершена');
});
7. Перехват необработанных ошибок Promise
Если ошибка не обработана, используй обработчик на уровне window:
// Обработка необработанных отклонений Promise
window.addEventListener('unhandledrejection', (event) => {
console.error('Необработанное отклонение Promise:', event.reason);
// event.preventDefault() - чтобы браузер не логировал ошибку
event.preventDefault();
});
// Тестирование
Promise.reject(new Error('Я не обработана!'));
// Будет поймана обработчиком unhandledrejection
8. Практический пример с React компонентом
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
let isMounted = true;
const loadUser = async () => {
try {
setLoading(true);
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
throw new Error(`User not found: ${response.status}`);
}
const userData = await response.json();
if (isMounted) {
setUser(userData);
setError(null);
}
} catch (err) {
if (isMounted) {
setError(err.message);
setUser(null);
}
} finally {
if (isMounted) {
setLoading(false);
}
}
};
loadUser();
// Cleanup функция
return () => {
isMounted = false;
};
}, [userId]);
if (loading) return <div>Загрузка...</div>;
if (error) return <div>Ошибка: {error}</div>;
if (!user) return <div>Пользователь не найден</div>;
return <div>Имя: {user.name}</div>;
}
Лучшие практики
- Всегда добавляй
.catch()- не оставляй неловленные ошибки - Используй async/await вместо цепочки
.then()для читаемости - Логируй ошибки - это поможет в отладке
- Показывай пользователю ошибку - если это пользовательское действие
- Используй
finally()- для очистки (закрытие загрузочных индикаторов, спиннеров) - Не игнорируй ошибки - даже если они неожиданные
- Разделяй обработку разных типов ошибок на разных уровнях
Обработка ошибок в Promises - это критически важная часть разработки надёжного и пользовательского приложения.