Как обрабатывать ошибки HTTP запросов
Что проверяют
Знаете ли вы, что ошибка запроса бывает разной природы: сеть, таймаут, статус 4xx или 5xx, неожиданное тело ответа, и что делать с каждой. Главная проверка на fetch: интервьюер ждёт, что вы скажете про response.ok. Следом обычно спрашивают про повторы и истёкший токен.
Как отвечать
Разделите ошибки по слоям:
fetch: промис отклоняется только при сетевой ошибке (TypeError) или отмене (DOMException). Ответ 404 или 500 считается успешным, поэтомуresponse.okиresponse.statusпроверяете сами;- axios: наоборот, отклоняет промис на любом статусе вне 2xx, это настраивается через
validateStatus. В ошибке естьerror.response, если сервер ответил, и толькоerror.request, если ответа не было; - таймаут: у
fetchего нет, нуженAbortControllerилиAbortSignal.timeout(ms); - тело ошибки: вместо JSON может прийти HTML страница прокси, и
response.json()упадёт сSyntaxError. Смотрите наContent-Type, для API удобен форматapplication/problem+json.
Всё это удобно собрать в одной обёртке над fetch или в интерцепторах axios: она превращает любую ошибку в единый тип с кодом, статусом и текстом для пользователя.
Реакция по статусам: 400 и 422 обычно означают ошибки валидации, их показывают у полей формы; на 401 пробуют обновить токен (один запрос обновления на все параллельные вызовы) и иначе ведут на вход; 403 это экран «нет доступа»; 404 это пустое состояние; 429 и 5xx можно повторять с экспоненциальной задержкой и с учётом Retry-After, но только идемпотентные запросы. TanStack Query по умолчанию повторяет упавший запрос три раза, а мутации не повторяет.
Пользователю нужны понятное сообщение и кнопка «Повторить», команде нужен отчёт в Sentry или аналоге с адресом и статусом.
Где спотыкаются
Оборачивают fetch в try/catch и ждут, что 500 попадёт в catch. Не попадёт.
Глотают ошибку: console.error в catch и неявный undefined в ответе, после чего компонент падает дальше на обращении к данным.
Повторяют POST оплаты при таймауте. Без ключа идемпотентности это двойное списание.