Как обработать сетевые ошибки при fetch
Что проверяют
Знаете ли вы главную особенность fetch: промис отклоняется только при сетевом сбое, а ответ 404 или 500 для него успешный. Следом обычно просят добавить таймаут и повторы и спрашивают, как отличить отмену запроса от настоящей ошибки.
Как отвечать
Разделите ошибки на классы, у каждого свой способ поймать:
- сетевой сбой: нет сети, не разрешился DNS, обрыв, запрет CORS.
fetchотклоняется сTypeError, текст сообщения у браузеров разный, поэтому по нему не ветвятся. Отличить CORS от обрыва из кода нельзя, это видно только в консоли; - HTTP-ошибка: промис выполнен, но
response.okравенfalseдля статусов вне диапазона от 200 до 299. Проверку и разбор тела ошибки пишут сами, удобно бросать свойHttpErrorсо статусом и телом; - таймаут: встроенного у
fetchнет. Передаютsignal: AbortSignal.timeout(10000), по истечении промис отклоняется сDOMExceptionпо имениTimeoutError; - отмена:
AbortController.abort(), например при уходе со страницы или смене фильтра, даёт ошибку с именемAbortError. Её не показывают пользователю как сбой; - битый ответ:
response.json()на HTML-странице ошибки от прокси бросаетSyntaxError, поэтому разбор тоже оборачивают вtry.
В коде это одна обёртка на async/await с try/catch, через которую идут все запросы. Повторы делают для сетевых сбоев, 5xx и 429 (с учётом Retry-After), с растущей паузой и только для идемпотентных методов. Пользователь видит понятное сообщение и кнопку «Повторить», а navigator.onLine с событием offline помогают показать плашку «Нет соединения». В React эту логику часто отдают TanStack Query, повторы там уже встроены.
Где спотыкаются
Пишут только .catch и уверены, что поймали всё. Ответ 500 проходит в .then и ломается уже на разборе данных.
Повторяют POST без ключа идемпотентности и создают дубли записей.
Показывают ошибку при AbortError: пользователь быстро переключил фильтр, а видит красное «Ошибка сети».