В этой статье демонстрируются некоторые подходы к обработке ошибок при работе с Fetch API . Fetch API позволяет вам сделать запрос к удаленному сетевому ресурсу. Когда вы совершаете удаленный сетевой вызов, ваша веб-страница становится подверженной множеству потенциальных сетевых ошибок.
В следующих разделах описываются потенциальные ошибки и описывается, как писать код, обеспечивающий разумный уровень функциональности, устойчивый к ошибкам и непредвиденным сетевым условиям. Гибкий код делает ваших пользователей счастливыми и поддерживает стандартный уровень обслуживания вашего веб-сайта.
Предвидеть потенциальные сетевые ошибки
В этом разделе описан сценарий, в котором пользователь создает новое видео с именем "My Travels.mp4"
, а затем пытается загрузить его на веб-сайт для обмена видео.
При работе с Fetch легко рассмотреть счастливый путь , когда пользователь успешно загружает видео. Однако есть и другие пути, которые не так гладки, но которые веб-разработчики должны планировать. Такие (несчастные) пути могут произойти из-за ошибки пользователя, неожиданных условий окружающей среды или из-за ошибки на веб-сайте обмена видео.
Примеры ошибок пользователей
- Пользователь загружает файл изображения (например, JPEG) вместо видеофайла.
- Пользователь начинает загружать не тот видеофайл. Затем, на полпути загрузки, пользователь указывает правильный видеофайл для загрузки.
- Пользователь случайно нажимает «Отменить загрузку» во время загрузки видео.
Примеры изменений окружающей среды
- Во время загрузки видео подключение к Интернету отключается.
- Браузер перезапускается во время загрузки видео.
- Серверы веб-сайта для обмена видео перезапускаются во время загрузки видео.
Примеры ошибок на сайте видеохостинга
- Веб-сайт обмена видео не может обрабатывать имя файла с пробелом. Вместо
"My Travels.mp4"
ожидается такое имя, как"My_Travels.mp4"
или"MyTravels.mp4"
. - Веб-сайт обмена видео не может загрузить видео, размер файла которого превышает максимально допустимый.
- Веб-сайт обмена видео не поддерживает видеокодек в загруженном видео.
Эти примеры могут иметь место и случаются в реальном мире. Возможно, вы уже сталкивались с такими примерами в прошлом! Давайте выберем по одному примеру из каждой из предыдущих категорий и обсудим следующие моменты:
- Каково поведение по умолчанию, если служба обмена видео не может обработать данный пример?
- Что ожидает пользователь в этом примере?
- Как мы можем улучшить этот процесс?
Обработка ошибок с помощью Fetch API
Обратите внимание, что в следующих примерах кода используется await
верхнего уровня ( поддержка браузера ), поскольку эта функция может упростить ваш код.
Когда Fetch API выдает ошибки
В этом примере используется оператор блока try
/ catch
для обнаружения любых ошибок, возникающих в блоке try
. Например, если Fetch API не может получить указанный ресурс, выдается ошибка. В таком блоке catch
позаботьтесь о том, чтобы обеспечить значимый пользовательский опыт. Если пользователю отображается счетчик, общий пользовательский интерфейс, который отображает какой-то прогресс, то вы можете выполнить следующие действия внутри блока catch
:
- Удалите счетчик со страницы.
- Предоставляйте полезные сообщения, объясняющие, что пошло не так и какие варианты действий может предпринять пользователь.
- На основе доступных опций предоставьте пользователю кнопку «Попробовать еще раз».
- В фоновом режиме отправьте подробную информацию об ошибке в службу отслеживания ошибок или на серверную часть. Это действие регистрирует ошибку, чтобы ее можно было диагностировать на более позднем этапе.
try {
const response = await fetch('https://website');
} catch (error) {
// TypeError: Failed to fetch
console.log('There was an error', error);
}
На более позднем этапе, пока вы диагностируете зарегистрированную ошибку, вы можете написать тестовый пример , чтобы отловить такую ошибку, прежде чем ваши пользователи поймут, что что-то не так. В зависимости от ошибки тест может быть модульным, интеграционным или приемочным.
Когда код состояния сети указывает на ошибку
В этом примере кода выполняется запрос к службе тестирования HTTP, которая всегда отвечает кодом состояния HTTP 429 Too Many Requests
. Интересно, что ответ не доходит до блока catch
. Статус 404, среди некоторых других кодов состояния, не возвращает сетевую ошибку , а вместо этого разрешается нормально.
Чтобы проверить, что код состояния HTTP прошел успешно, вы можете использовать любой из следующих вариантов:
- Используйте свойство
Response.ok
, чтобы определить, находится ли код состояния в диапазоне от200
до299
. - Используйте свойство
Response.status
, чтобы определить, был ли ответ успешным. - Используйте любые другие метаданные, такие как
Response.headers
, чтобы оценить, был ли ответ успешным.
let response;
try {
response = await fetch('https://httpbin.org/status/429');
} catch (error) {
console.log('There was an error', error);
}
// Uses the 'optional chaining' operator
if (response?.ok) {
console.log('Use the response here!');
} else {
console.log(`HTTP Response Code: ${response?.status}`)
}
Лучше всего работать с людьми в вашей организации и команде, чтобы понять потенциальные коды состояния ответа HTTP. Бэкэнд-разработчики, специалисты по эксплуатации и сервисные инженеры иногда могут предоставить уникальную информацию о возможных крайних случаях, которые вы, возможно, не ожидаете.
При возникновении ошибки анализа ответа сети
В этом примере кода демонстрируется другой тип ошибки, которая может возникнуть при анализе тела ответа. Интерфейс Response
предлагает удобные методы для анализа различных типов данных, таких как текст или JSON. В следующем коде выполняется сетевой запрос к службе тестирования HTTP, которая возвращает строку HTML в качестве тела ответа. Однако предпринимается попытка проанализировать тело ответа как JSON , что приводит к ошибке.
let json;
try {
const response = await fetch('https://httpbin.org/html');
json = await response.json();
} catch (error) {
if (error instanceof SyntaxError) {
// Unexpected token < in JSON
console.log('There was a SyntaxError', error);
} else {
console.log('There was an error', error);
}
}
if (json) {
console.log('Use the JSON here!', json);
}
Вы должны подготовить свой код для приема различных форматов ответов и убедиться, что неожиданный ответ не нарушит работу веб-страницы для пользователя.
Рассмотрим следующий сценарий: у вас есть удаленный ресурс, который возвращает действительный ответ JSON и успешно анализируется с помощью метода Response.json()
. Может случиться так, что услуга отключится. При отключении возвращается 500 Internal Server Error
. Если во время анализа JSON не используются соответствующие методы обработки ошибок, это может привести к поломке страницы для пользователя, поскольку возникнет необработанная ошибка.
Когда сетевой запрос необходимо отменить до его завершения
В этом примере кода используется AbortController
для отмены текущего запроса. Текущий запрос — это сетевой запрос, который начался, но не завершился.
Сценарии, в которых вам может потребоваться отменить текущий запрос, могут различаться, но в конечном итоге это зависит от вашего варианта использования и среды. Следующий код демонстрирует, как передать AbortSignal
в Fetch API. AbortSignal
прикреплен к AbortController
, а AbortController
включает метод abort()
, который сообщает браузеру, что сетевой запрос следует отменить.
const controller = new AbortController();
const signal = controller.signal;
// Cancel the fetch request in 500ms
setTimeout(() => controller.abort(), 500);
try {
const url = 'https://httpbin.org/delay/1';
const response = await fetch(url, { signal });
console.log(response);
} catch (error) {
// DOMException: The user aborted a request.
console.log('Error: ', error)
}
Заключение
Одним из важных аспектов обработки ошибок является определение различных частей, которые могут пойти не так. Для каждого сценария убедитесь, что у вас есть подходящий резервный вариант для пользователя. Что касается запроса на выборку, задайте себе такие вопросы, как:
- Что произойдет, если целевой сервер выйдет из строя?
- Что произойдет, если Fetch получит неожиданный ответ?
- Что произойдет, если у пользователя произойдет сбой подключения к Интернету?
В зависимости от сложности вашей веб-страницы вы также можете набросать блок-схему, описывающую функциональность и пользовательский интерфейс для различных сценариев.