Как организовать API слой во frontend?
Что проверяют
Есть ли у вас граница между интерфейсом и сетью: компоненты не должны знать про URL, заголовки и коды ответа. Следом спрашивают, где живёт кэш серверных данных и как вы обновляете токен, когда несколько запросов одновременно получили 401.
Как отвечать
Опишите слои снизу вверх:
- HTTP-клиент: одна обёртка над
fetchили экземплярaxios.create()сbaseURL, заголовками, авторизацией и таймаутом черезAbortSignal.timeout(). Здесь же ошибки приводятся к одному классуApiErrorсо статусом и кодом; - модули эндпоинтов:
api/users.ts,api/orders.ts, типизированные функции вродеgetUser(id): Promise<User>. Типы лучше генерировать из OpenAPI (openapi-typescript, orval), а ответ чужого API проверять через zod; - серверное состояние: TanStack Query, RTK Query или SWR. Они дают кэш, дедупликацию одинаковых запросов, повторы, отмену и инвалидацию после мутации по ключам. Redux или Context для этого не нужны, они про клиентское состояние;
- хуки уровня фичи:
useUser(id)поверх запроса, компонент зовёт только его.
Сквозные вещи тоже живут в клиенте. Обновление токена по 401 делается одним запросом на refresh, а остальные упавшие запросы ждут его результат и повторяются. Retry только для идемпотентных методов. Устаревшие запросы отменяются через AbortController, чтобы ответ на старый поиск не перезаписал новый.
Для тестов и Storybook слой подменяют через MSW, код приложения при этом не меняется. В Next.js с серверными компонентами часть запросов уходит на сервер, и модули эндпоинтов должны работать в обоих окружениях.
Где спотыкаются
Забывают, что fetch не отклоняет промис на 404 и 500, только на сетевую ошибку. Без проверки response.ok ошибка сервера разбирается как успешный JSON. У axios наоборот: ответ не из диапазона 2xx по умолчанию уходит в catch.
Кладут ответы сервера в Redux руками и сами пишут флаги загрузки, кэш и инвалидацию. Получается кустарная копия библиотеки для серверного состояния.
Делают refresh в интерсепторе без очереди. Пять параллельных запросов получают 401, уходят пять refresh, и сервер с ротацией токенов разлогинивает пользователя.