Gernar
Frontend DeveloperHTTP, API и сеть

Интервью-вопрос

Что использовал для взаимодействия с сервером

Отвечайте через задачи, а не через список библиотек. HTTP-запросы, кэш, авторизация, ошибки, real-time и типизация контракта. Главный риск в ответе, показать, что вы дергали API, но не управляли состоянием и сбоями.

Добавлен
Редакция

Подготовьте короткий ответ и пару деталей на случай уточняющих вопросов.

🐰0
🥚0

Мини-квиз

Проверка перед разбором

Несколько быстрых вопросов перед разбором. Так проще поймать места, которые только кажутся понятными.

Вопрос 1 из 60 правильно

Как лучше начать ответ на вопрос про взаимодействие с сервером?

Вы сейчас хотите звучать как практик, а не как человек, который просто перечисляет библиотеки.

Варианты ответа

Разбор

Разобраться, а не зазубрить

Дальше разбираем суть, типичные уточнения и места, где легко сказать лишнее или перепутать термины.

Базовая идея

Этот вопрос не про то, знаете ли вы названия fetch, axios или socket.io. Он про то, как вы строите слой общения с backend. Где храните серверные данные, как показываете загрузку, что делаете при ошибке, как защищаете авторизацию и как не ломаете UI гонками запросов.

Хороший ответ удобно строить так. Сначала назовите основные инструменты из своего опыта. Затем привяжите каждый к задаче. После этого добавьте риски и способы защиты. Например, Fetch или Axios для HTTP, React Query или SWR для кэша, WebSocket для событий, GraphQL для гибких выборок, OpenAPI или codegen для типов.

Не нужно делать вид, что вы использовали все сразу. Если в вашем опыте был только REST и Axios, это нормально. Сильнее звучит честный ответ с обработкой ошибок, retry, отменой запросов и понятным UI, чем длинный список технологий без деталей.

Как выбрать формулировку ответа

Можно ответить коротко, но с практическим фокусом:

В последнем проекте основное взаимодействие с сервером было через REST API. Для запросов использовали Axios с общим API-клиентом, interceptors для авторизации и обработки 401, а серверное состояние на экранах держали через React Query. Это помогало не писать вручную кэш, loading, retry и invalidation после сохранения формы.

Если у вас похожая ситуация, замените детали на свои. Если вы работали с Fetch, скажите про wrapper, проверку response.ok и AbortController. Если работали без React Query, объясните, как сами решали кэш, отмену запросов и сброс состояния при ошибке.

Сильный ответ
  1. 1Назвать 2-3 инструмента из своего опыта
  2. 2Привязать каждый инструмент к задаче
  3. 3Сказать, как обрабатывались ошибки и загрузка
  4. 4Упомянуть кэш, отмену запросов или invalidation
  5. 5Закончить trade-off: когда инструмент не нужен
Слабый ответ
  1. 1Перечислить библиотеки без контекста
  2. 2Не сказать про статусы и сетевые сбои
  3. 3Смешать WebSocket, REST и GraphQL как взаимозаменяемые вещи
  4. 4Забыть про cleanup и race conditions
  5. 5Сделать вид, что выбор всегда очевиден

Как выбирать инструмент под задачу

Самый безопасный ответ на интервью показывает критерий выбора. Не говорите, что Axios всегда лучше Fetch или что GraphQL всегда лучше REST. В реальном проекте важны размер приложения, требования к кэшу, соглашения команды, типизация контракта, авторизация и поддержка ошибок.

Например, для лендинга с одним запросом за настройками хватит Fetch. Для кабинета с десятками endpoint, токенами и единым форматом ошибок удобнее API-клиент. Для таблиц, фильтров и повторного открытия экранов полезен React Query или SWR. Для чата, уведомлений и статусов задач нужен real-time транспорт, но вместе с логикой восстановления состояния.

Как объяснить выбор инструмента

1Нужен один простой запрос без общего клиента?
Fetch с явной проверкой response.ok и AbortController.
2Нужны baseURL, interceptors, единый формат ошибок и refresh token flow?
Axios или свой API-клиент поверх fetch.
3Нужно кэширование, retry, invalidation и фоновые обновления?
React Query, SWR или похожий слой server state.
4Нужны события в реальном времени?
WebSocket, SSE или socket.io, плюс reconnect и синхронизация после обрыва.
5Экрану нужны гибкие выборки полей и связанные сущности?
GraphQL, если команда готова поддерживать схему, типы и кэш.

Пример безопасного HTTP-клиента

Плохой вариант: сделать fetch, сразу вызвать response.json() и считать, что catch поймает все ошибки. При 500 promise не упадет сам, и вы можете показать пользователю некорректный экран.

Более безопасный базовый wrapper:

async function requestJson<T>(url: string, signal?: AbortSignal): Promise<T> {
  const response = await fetch(url, {
    signal,
    headers: {
      Accept: "application/json",
    },
  });

  if (!response.ok) {
    throw new Error(`Request failed with status ${response.status}`);
  }

  return response.json() as Promise<T>;
}

const controller = new AbortController();

requestJson<User[]>("/api/users", controller.signal)
  .then(setUsers)
  .catch((error) => {
    if (error.name === "AbortError") return;
    setError("Не удалось загрузить пользователей");
  });

// при размонтировании компонента
controller.abort();

На интервью не обязательно писать такой код целиком. Достаточно сказать идею: проверяю статус, нормализую ошибку, отменяю устаревший запрос, не оставляю экран в бесконечной загрузке.

Ошибки, загрузка и состояние UI

Работа с сервером во фронтенде почти всегда упирается в состояние. Для пользователя важны не названия библиотек, а то, что экран показывает правильный статус: идет загрузка, данных нет, нет доступа, форма не прошла валидацию, сервер временно недоступен или данные устарели.

Разделяйте ошибки по смыслу. 401 часто ведет к refresh token flow или выходу. 403 означает, что действие запрещено. 422 обычно нужно привязать к полям формы. 409 говорит о конфликте состояния, например кто-то уже изменил сущность. 500 лучше показать как временный сбой и дать повторить действие.

Если вы делали optimistic UI, скажите про rollback. Например, лайк можно показать сразу, но при ошибке нужно вернуть состояние назад или явно сказать пользователю, что действие не сохранилось. Иначе UI будет врать, а следующий refetch внезапно откатит данные.

Авторизация и безопасность

Если вы упоминаете interceptors или middleware API-клиента, не ограничивайтесь фразой про добавление JWT. Скажите, где обрабатывался 401, как не допускали бесконечных refresh-запросов и что происходило с несколькими параллельными запросами, когда сессия истекла.

Не стоит уверенно говорить, что токен всегда можно хранить в localStorage. Это зависит от модели угроз и backend-архитектуры. Для cookie-based auth важны SameSite, CSRF-защита и корректные CORS-настройки. Для bearer token в JS-коде важен риск XSS и аккуратная работа с секретами.

Отдельный риск - вывод данных из API. Комментарии, описания из CMS и HTML-фрагменты нельзя бездумно вставлять через dangerouslySetInnerHTML. Так можно открыть XSS, сломать верстку или дать чужому скрипту доступ к данным страницы. Безопаснее рендерить обычный текст, валидировать формат ответа и очищать HTML до попадания в компонент.

Практичный ответ звучит так: я не решаю безопасность только на фронтенде, но понимаю последствия выбранной схемы для UI, заголовков, refresh flow, logout, безопасного рендера данных и обработки ошибок доступа.

Real-time, GraphQL и типизация

WebSocket, SSE и GraphQL лучше упоминать только если они реально были в вашем опыте или вы можете объяснить сценарий. WebSocket нужен для двусторонних событий: чат, статусы задач, уведомления, совместное редактирование. SSE проще для потока событий от сервера к клиенту. GraphQL полезен, когда экрану нужны связанные данные и точный набор полей.

Для real-time важно сказать про жизненный цикл: открыть соединение, подписаться, обработать сообщение, закрыть при размонтировании, переподключиться после обрыва и синхронизировать состояние. Для GraphQL важно не только query, но и кэш, fragments, generated types и обработка частичных ошибок.

Если в проекте была типизация контракта через OpenAPI, Swagger, GraphQL codegen или общий пакет типов, обязательно упомяните это. Это сильный плюс. Так вы снижаете риск, что backend поменяет поле, а фронтенд узнает об этом только в runtime.

Практический вывод

Сильный ответ на этот вопрос можно держать в голове как короткую схему: инструменты, задачи, ошибки, состояние, безопасность, trade-off. Не пытайтесь назвать все технологии. Лучше показать 2-3 реальных сценария и объяснить, какие проблемы вы там решали.

Если опыта мало, не выдумывайте GraphQL или WebSocket. Скажите честно: работал с REST, Fetch или Axios, делал обработку loading и error states, проверял статусы, отменял запросы при размонтировании, понимаю, когда стоит добавить React Query или SWR. Такой ответ выглядит спокойнее и надежнее, чем преувеличение.

Частые ошибки

Где обычно ошибаются

Проверьте формулировки, которые звучат уверенно, но на интервью быстро выдают пробелы.

  1. 1

    Перечислять инструменты без задач

    Ответ в стиле fetch, axios, socket.io, Apollo звучит как список из резюме. Лучше сразу связать инструмент с задачей. Запросы, кэш, авторизация, real-time, генерация типов. Так видно, что вы выбирали решение, а не просто копировали стек проекта.
  2. 2

    Не проверять response.ok во Fetch

    fetch отклоняет promise при сетевой ошибке, но не при 404 или 500. Если не проверить response.ok, UI может попытаться работать с ошибочным ответом как с успешными данными. Безопаснее сделать общий wrapper и нормализовать ошибки.
  3. 3

    Не отменять устаревшие запросы

    Быстрый переход между страницами или быстрый ввод в поиске может привести к race condition. Старый ответ придет позже нового и перезапишет актуальные данные. Используйте AbortController, механизмы React Query или проверку актуальности запроса.
  4. 4

    Считать WebSocket заменой всем API

    WebSocket хорош для событий, но не обязан хранить полное состояние клиента. После разрыва соединения можно потерять часть событий, поэтому часто нужен обычный запрос для восстановления актуального состояния. В ответе лучше сказать про reconnect, heartbeat и resync.
  5. 5

    Обрабатывать все ошибки одним toast

    401, 403, 409, 422 и 500 требуют разных действий. Один общий toast скрывает проблему и ухудшает UX. Лучше разделять авторизацию, права доступа, конфликт данных, валидацию формы и сбой сервера.
  6. 6

    Доверять HTML и тексту с сервера

    Ответ API нельзя считать безопасным только потому, что он пришел от вашего backend. Если вывести поле через dangerouslySetInnerHTML без очистки, можно получить XSS и утечку токена или данных пользователя. Безопаснее рендерить текст как текст, валидировать формат ответа и очищать HTML на доверенной стороне.

Follow-up

Что могут спросить дальше

Короткие ответы на вопросы, которыми проверяют ваш реальный опыт работы с API, ошибками, кэшем и real-time.

Живые ответы

Видео с похожим вопросом

Если найдем публичные интервью с таким вопросом, добавим их сюда. Их удобно смотреть после теории, чтобы свериться с живыми ответами.

Пока видео нет. Когда появятся подходящие публичные интервью, добавим их в этот блок, чтобы можно было сравнить разбор с тем, как отвечают реальные кандидаты.

Содержание