Зачем fetch не отклоняет promise при статусе Not OK?
Быстрый ответ
Для эффективной обработки ошибок в fetch
следует контролировать свойство response.ok
. Если его значение — false
, следует генерировать исключение. Пример проверки выглядит следующим образом:
fetch('url')
.then(response => {
if (!response.ok) throw new Error(response.statusText); // Если статус ответа не OK, генерируем исключение
return response.json();
})
.catch(error => console.error("Возникла ошибка при выполнении Fetch:", error));
Сначала выполняем проверку статуса ответа, затем в случае обнаружения ошибки генерируем исключение, после чего перехватываем данное исключение для его последующей обработки. Просто и логично.
Обработка различных HTTP-статусов
Приведённый выше метод оптимален для простой обработки ошибок. Вместе с тем, иногда необходимо учитывать конкретные HTTP-статусы и разрабатывать различные сценарии их обработки. Иными словами, подготовить следующий пример:
function handleErrors(response) {
if (!response.ok) {
var error = new Error(response.statusText);
error.response = response;
throw error; // Не стоит избегать генерации исключения
}
return response;
}
fetch(url)
.then(handleErrors)
.then(response => response.json())
.catch(error => console.error('Ошибка в результате выполнения Fetch:', error));
Пример с неудачным прохождением авторизации
Если запрос авторизации возвращает статус 401
, можно перенаправить пользователя на страницу для входа в систему или выдать ему предупреждающее сообщение.
Пример с отсутствием ресурса
При получении от сервера статуса 404
подойдет специальное сообщение об ошибке или же перенаправление пользователя на страницу поиска.
Пример с ошибкой сервера
С ошибками сервера, кодируемыми статусом 5XX
, стоит рассмотреть возможность повторного отправления запроса или об информировании пользователя с просьбой повторить попытку позднее.
Визуализация
Представим обработку ответов fetch
в виде контроля качества на ленте производства:
'fetch(url)': [📦, 📦, 📦, 📦] // Каждая коробка представляет собой ответ
Контроль качества: Мы проверяем каждую коробку (ответ)
if (!response.ok) throw new Error('🔴'); // Отбраковываем некачественный продукт
return response; // Принимаем качественный продукт
А управлять процессом проще всего через .then()
и .catch()
:
fetch(url)
.then(response => {
if (!response.ok) throw new Error('🔴'); // Отбраковываем некачественную коробку
return response;
})
.then(data => console.log('📦✅')) // Допускаем качественные коробки дальше
.catch(error => console.log('🔴⛔')); // Сортируем бракованные коробки
📦✅ = Получаем правильный ответ
🔴⛔ = Обрабатываем ошибочный ответ
Аналогия поможет запомнить: мы отсеиваем некачественные коробки, передавая далее только качественные.
Применение Async/await для повышения читаемости кода
Синтаксис async/await обеспечивает более структурированный и понятный код, дающий ощущение его последовательного исполнения:
async function fetchData(url) {
try {
const response = await fetch(url);
if (!response.ok) throw new Error(response.statusText); // Если статус не OK, вызываем исключение сразу
const data = await response.json();
return data;
} catch (error) {
console.error('Fetch завершился с ошибкой:', error);
}
}
Более удобное управление через try-catch
Используя структуру try-catch
, упрощаем управление ошибками, делая код более подобным на синхронный.
Повышенная читаемость
Избегая использования цепочек .then()
, переместив обработку ошибок в catch
, улучшаем визуальное восприятие кода, что особенно важно при решении сложных задач.
Облегченное управление ошибками
Выбрасывание исключения в try
автоматически приводит к отмене промиса, который затем можно обработать в catch
.
Универсальная обработка ошибок
Создание общей системы для обработки ошибок предполагает применение единого подхода или функций для однообразного реагирования на различные ответы.
function errorHandler(status) {
switch (status) {
case 400:
return 'Недопустимый запрос';
case 401:
return 'Нет авторизации. Перенаправляем на страницу входа...';
case 404:
return 'Ресурс отсутствует. Возможно, его удалили или переместили.';
// ... Дальнейшие случаи по необходимости
default:
return 'Возникла неизвестная ошибка. Пожалуйста, попробуйте еще раз позже.';
}
}
fetch(url)
.then(response => response.ok ? response.json() : Promise.reject(errorHandler(response.status)))
.catch(error => console.error(error));
Связывая конкретные сообщения с различными HTTP-кодами, мы улучшаем информирование пользователей. Данный метод гарантирует, что мы способны реагировать на заранее известные проблемы, а также на непредвиденные события, обеспечивая масштабируемость системы и упрощая добавление новых сценариев обработки.
Полезные материалы
- Использование Fetch API – Веб API | MDN — Детальная информация о Fetch API для отправки HTTP-запросов.
- Promise – JavaScript | MDN — Методы управления ошибками с использованием промисов в JavaScript.
- Управление ошибками HTTP-ответов с помощью fetch() — Стратегии обработки статусов ошибок HTTP в fetch.
- Как использовать Fetch API JavaScript для получения данных — Руководство по использованию Fetch API JavaScript для извлечения данных.
- ES6 Promises подробно — Обстоятельный анализ промисов ES6 и способов их применения.
- Как использовать промисы – Учим веб-разработку | MDN — Введение в основные принципы и преимущества промисов в асинхронном JavaScript.
- PromiseRejectionEvent – Веб API | MDN — О том, что такое PromiseRejectionEvent и как работать с отклоненными промисами.