Реализуйте обработку ошибок при использовании Fetch API.

В этой статье демонстрируются некоторые подходы к обработке ошибок при работе с Fetch API . Fetch API позволяет вам сделать запрос к удаленному сетевому ресурсу. Когда вы совершаете удаленный сетевой вызов, ваша веб-страница становится подверженной множеству потенциальных сетевых ошибок.

В следующих разделах описываются потенциальные ошибки и описывается, как писать код, обеспечивающий разумный уровень функциональности, устойчивый к ошибкам и непредвиденным сетевым условиям. Гибкий код делает ваших пользователей счастливыми и поддерживает стандартный уровень обслуживания вашего веб-сайта.

Предвидеть потенциальные сетевые ошибки

В этом разделе описывается сценарий, в котором пользователь создает новое видео с именем "My Travels.mp4" , а затем пытается загрузить его на веб-сайт для обмена видео.

При работе с Fetch легко рассмотреть счастливый путь , когда пользователь успешно загружает видео. Однако есть и другие пути, которые не так гладки, но которые веб-разработчики должны планировать. Такие (несчастливые) пути могут произойти из-за ошибки пользователя, неожиданных условий окружающей среды или из-за ошибки на веб-сайте обмена видео.

Примеры ошибок пользователей

  • Пользователь загружает файл изображения (например, JPEG) вместо видеофайла.
  • Пользователь начинает загружать не тот видеофайл. Затем, на полпути загрузки, пользователь указывает правильный видеофайл для загрузки.
  • Пользователь случайно нажимает «Отменить загрузку» во время загрузки видео.

Примеры изменений окружающей среды

  • Во время загрузки видео подключение к Интернету отключается.
  • Браузер перезапускается во время загрузки видео.
  • Серверы веб-сайта для обмена видео перезапускаются во время загрузки видео.

Примеры ошибок на сайте видеохостинга

  • Веб-сайт обмена видео не может обрабатывать имя файла с пробелом. Вместо "My Travels.mp4" ожидается такое имя, как "My_Travels.mp4" или "MyTravels.mp4" .
  • Веб-сайт обмена видео не может загрузить видео, размер файла которого превышает максимально допустимый.
  • Веб-сайт обмена видео не поддерживает видеокодек в загруженном видео.

Эти примеры могут иметь место и случаются в реальном мире. Возможно, вы уже сталкивались с такими примерами в прошлом! Давайте выберем по одному примеру из каждой из предыдущих категорий и обсудим следующие моменты:

  • Каково поведение по умолчанию, если служба обмена видео не может обработать данный пример?
  • Что ожидает пользователь в этом примере?
  • Как мы можем улучшить этот процесс?
Действие Пользователь начинает загружать не тот видеофайл. Затем, на этапе загрузки, пользователь указывает правильный видеофайл для загрузки.
Что происходит по умолчанию Исходный файл продолжает загружаться в фоновом режиме, в то время как новый файл загружается одновременно.
Чего ожидает пользователь Пользователь ожидает, что первоначальная загрузка прекратится, чтобы не тратить лишнюю пропускную способность Интернета.
Что можно улучшить JavaScript отменяет запрос Fetch для исходного файла до того, как новый файл начнет загружаться.
Действие Пользователь теряет подключение к Интернету на этапе загрузки видео.
Что происходит по умолчанию Индикатор выполнения загрузки застрял на 50 %. В конце концов у Fetch API истекает время ожидания, и загруженные данные удаляются. Когда подключение к Интернету восстанавливается, пользователю необходимо повторно загрузить файл.
Чего ожидает пользователь Пользователь ожидает, что его уведомят, если его файл не может быть загружен, и он ожидает, что его загрузка автоматически возобновится на уровне 50%, когда он снова будет в сети.
Что можно улучшить Страница загрузки информирует пользователя о проблемах с подключением к Интернету и заверяет пользователя, что загрузка возобновится после возобновления подключения к Интернету.
Действие Веб-сайт обмена видео не может обрабатывать имя файла с пробелом. Вместо «My Travels.mp4» он ожидает такие имена, как «My_Travels.mp4» или «MyTravels.mp4».
Что происходит по умолчанию Пользователь должен дождаться полного завершения загрузки. Когда файл загружен и индикатор выполнения показывает «100%», на индикаторе выполнения отображается сообщение: «Пожалуйста, повторите попытку».
Чего ожидает пользователь Пользователь ожидает, что ему сообщат об ограничениях имени файла до начала загрузки или, по крайней мере, в течение первой секунды после загрузки.
Что можно улучшить В идеале служба обмена видео поддерживает имена файлов с пробелами. Альтернативные варианты — уведомить пользователя об ограничениях имени файла перед началом загрузки. Или служба обмена видео должна отклонить загрузку с подробным сообщением об ошибке.

Обработка ошибок с помощью Fetch API

Обратите внимание, что в следующих примерах кода используется await верхнего уровня ( поддержка браузера ), поскольку эта функция может упростить ваш код.

Когда Fetch API выдает ошибки

В этом примере используется оператор блока try / catch для обнаружения любых ошибок, возникающих в блоке try . Например, если Fetch API не может получить указанный ресурс, выдается ошибка. В таком блоке catch позаботьтесь о том, чтобы обеспечить значимый пользовательский опыт. Если пользователю отображается счетчик, общий пользовательский интерфейс, который отображает какой-то прогресс, то вы можете выполнить следующие действия внутри блока catch :

  1. Удалите счетчик со страницы.
  2. Предоставляйте полезные сообщения, объясняющие, что пошло не так и какие варианты действий может предпринять пользователь.
  3. На основе доступных опций предоставьте пользователю кнопку «Попробовать еще раз».
  4. В фоновом режиме отправьте подробную информацию об ошибке в службу отслеживания ошибок или на серверную часть. Это действие регистрирует ошибку, чтобы ее можно было диагностировать на более позднем этапе.
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 получит неожиданный ответ?
  • Что произойдет, если у пользователя произойдет сбой подключения к Интернету?

В зависимости от сложности вашей веб-страницы вы также можете набросать блок-схему, описывающую функциональность и пользовательский интерфейс для различных сценариев.