Как проверить статус ответа и обработать response not ok
Что проверяют
Знаете ли вы, что fetch не считает ответ 404 или 500 ошибкой. Интервьюер хочет увидеть, как вы отделяете сетевой сбой от ошибки HTTP и что показываете пользователю в каждом случае. Следом обычно спрашивают про таймаут и про то, как это устроено в axios.
Как отвечать
Промис fetch отклоняется только при сетевой ошибке, блокировке CORS или отмене через AbortController. Любой ответ сервера, включая 404 и 500, приходит как успешный, и проверять его нужно самому:
response.ok:trueдля статусов от 200 до 299, для остальныхfalse;response.status: конкретный код, по которому выбирается реакция.statusTextна HTTP/2 пустой, полагаться на него нельзя.
Рабочий каркас: обёртка над fetch, которая при !response.ok читает тело ошибки и бросает собственный HttpError со status и данными. Тело читают осторожно: сначала смотрят content-type, потому что прокси на 502 часто отдаёт HTML, и response.json() упадёт с SyntaxError.
Реакция по коду:
- 401: обновить токен или отправить на вход;
- 400 и 422: показать ошибки у конкретных полей формы;
- 429: подождать, учитывая заголовок
Retry-After; - 5xx: повторить с растущей задержкой, но только идемпотентные запросы;
- 204: тела нет,
json()вызывать не нужно.
Таймаут задаётся через signal: AbortSignal.timeout(10000), по истечении промис отклоняется с ошибкой TimeoutError. В axios логика обратная: он сам отклоняет промис на статусах вне 2xx, это настраивается через validateStatus. В TanStack Query queryFn обязана бросить ошибку, иначе ответ с 500 окажется в data.
Где спотыкаются
Оборачивают fetch в try/catch и считают, что ошибки обработаны. Ответ 500 в catch не попадёт.
Показывают одно сообщение на всё. Пользователь с истёкшей сессией и пользователь без интернета видят одинаковое «Что-то пошло не так».
Вызывают response.json() на любом ответе. На пустом 204 или HTML-странице ошибки это исключение, которое маскирует настоящую причину.