Gernar
Frontend DeveloperHTTP, API и сеть

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

Что такое Axios

Axios это библиотека для HTTP-запросов в JavaScript. В ответе важно не просто назвать библиотеку, а объяснить, зачем она нужна во фронтенде, чем отличается от fetch и какие риски закрывает.

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

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

🐰0
🥚0

Мини-квиз

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

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

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

Как коротко объяснить, что такое Axios?

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

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

Разбор

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

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

Базовая идея

Начните с прямого определения: Axios это библиотека для HTTP-запросов в JavaScript. Во фронтенде она часто работает как слой между UI и API. Компонент или сервис вызывает метод, Axios отправляет запрос, возвращает промис и дает доступ к данным ответа, статусу и заголовкам.

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

Что сказать коротко на интервью

Можно ответить так:

Axios это библиотека для HTTP-запросов. Она работает через промисы, упрощает отправку запросов к API, умеет автоматически сериализовать и парсить JSON, поддерживает interceptors, отдельные instances, timeout и отмену запросов. Я использую ее, когда нужен единый API-клиент и централизованная обработка авторизации или ошибок.

Сразу добавьте практический вывод:

Но сам Axios не решает все сетевые проблемы. В UI все равно нужно обрабатывать loading, ошибки, отмену старых запросов и разные HTTP-статусы, иначе можно получить плохой UX или race condition.

Чем Axios отличается от fetch

Сравнивайте спокойно. fetch это встроенный браузерный API, а Axios это внешняя библиотека. Поэтому fetch хорош для простых сценариев и не добавляет зависимость. Axios удобен, когда нужен готовый клиент с общей конфигурацией.

Самая частая ловушка на интервью связана с HTTP-ошибками. Axios по умолчанию считает успешными только статусы 2xx. Если сервер вернул 404 или 500, промис будет отклонен. У fetch ответ с 404 обычно не попадает в catch, потому что запрос технически дошел до сервера. Там нужно проверять response.ok.

// fetch: 404 не обязательно попадет в catch
const response = await fetch("/api/users/42");

if (!response.ok) {
  throw new Error(`HTTP error: ${response.status}`);
}

const data = await response.json();

// axios: 404 по умолчанию попадет в catch
try {
  const response = await api.get("/users/42");
  console.log(response.data);
} catch (error) {
  console.error(error.response?.status);
}

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

Когда Axios действительно полезен

Как выбрать подход

1Нужен один простой запрос без общего клиента?
Можно оставить <code>fetch</code>, чтобы не добавлять зависимость.
2В проекте много запросов к одному API?
Создайте <code>axios.create</code> с <code>baseURL</code>, общими заголовками и timeout.
3Нужна авторизация или единая обработка 401?
Axios удобен через request и response interceptors, но их лучше держать в одном модуле.
4Запрос зависит от состояния UI или маршрута?
Добавьте отмену через <code>AbortController</code>, чтобы старый ответ не перезаписал новый экран.

В реальном проекте Axios чаще всего ценен не из-за короткого синтаксиса, а из-за повторного использования настроек. Например, можно создать отдельный клиент для API и не размазывать baseURL, timeout и заголовки по компонентам.

import axios from "axios";

export const api = axios.create({
  baseURL: "/api",
  timeout: 10_000,
});

api.interceptors.request.use((config) => {
  const token = getAccessToken();

  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }

  return config;
});

api.interceptors.response.use(
  (response) => response,
  (error) => {
    if (error.response?.status === 401) {
      logoutUser();
    }

    return Promise.reject(error);
  }
);

Такой код лучше держать рядом с API-слоем, а не внутри UI-компонента. Иначе interceptor может зарегистрироваться несколько раз, начать дублировать действия и усложнить отладку.

Как обрабатывать ошибки

Что различать в catch

HTTP-ошибкаerror.response

Сервер ответил 4xx или 5xx. Покажите понятное сообщение, не теряйте статус и тело ответа.

Нет ответаerror.request

Запрос ушел, но ответа нет. Это похоже на сеть, CORS, timeout или недоступный сервер.

Ошибка настройкиerror.message

Запрос не собрался из-за неправильного URL, config или interceptor. Это повод логировать техническую причину.

ОтменаAbortController

Запрос больше не нужен. Не показывайте это как ошибку пользователю и не перетирайте актуальное состояние.

В ответе полезно показать, что вы не ограничиваетесь фразой "добавлю catch". Ошибки бывают разными. Если есть error.response, сервер вернул ответ, и можно смотреть статус. Если есть error.request, ответ не пришел. Если нет ни того, ни другого, проблема могла быть в настройке запроса.

Для пользователя эти случаи выглядят по-разному. При 401 можно предложить войти снова, при 404 показать пустое состояние или сообщение "не найдено", при 409 объяснить конфликт данных, при timeout дать повторить запрос. Один общий toast "что-то пошло не так" быстро превращается в плохой UX и мешает поддержке.

Отмена запросов и React

В React запрос может устареть раньше, чем завершится. Например, пользователь печатает в поиске, меняет фильтр или уходит со страницы. Если старый ответ придет позже нового, он может перезаписать актуальные данные. Для живого поиска часто добавляют debounce, чтобы не слать запрос на каждую букву, а отмена защищает от устаревших ответов.

import { useEffect, useState } from "react";
import { api } from "./api";

export function UsersList({ query }) {
  const [users, setUsers] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    const controller = new AbortController();

    async function loadUsers() {
      setIsLoading(true);
      setError(null);

      try {
        const response = await api.get("/users", {
          params: { query },
          signal: controller.signal,
        });

        if (!Array.isArray(response.data)) {
          throw new Error("Unexpected users response");
        }

        setUsers(response.data);
      } catch (error) {
        if (controller.signal.aborted) {
          return;
        }

        setUsers([]);
        setError(error);
      } finally {
        if (!controller.signal.aborted) {
          setIsLoading(false);
        }
      }
    }

    loadUsers();

    return () => {
      controller.abort();
    };
  }, [query]);

  if (isLoading) {
    return <p role="status">Загружаем пользователей...</p>;
  }

  if (error) {
    return <p role="alert">Не удалось загрузить пользователей.</p>;
  }

  if (users.length === 0) {
    return <p>Пользователи не найдены.</p>;
  }

  return (
    <ul>
      {users.map((user) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

Здесь важна не сама библиотека, а правило: запрос, который больше не нужен, не должен обновлять UI. Пример также разделяет loading, error и empty state. Это защищает от зависшего интерфейса, race condition и тихого падения при неожиданном формате ответа. На интервью это звучит сильнее, чем просто "Axios поддерживает отмену".

Безопасный flow для фронтенда

Безопасный flow
  1. 1Создать отдельный axios instance для API
  2. 2Поставить timeout и нужные заголовки
  3. 3Отменять устаревший запрос через signal
  4. 4Разделить loading, success, empty и error состояния
  5. 5Проверить формат ответа перед обновлением UI
  6. 6Обработать 401, 403, 404, 409 и 500 по смыслу
Опасный flow
  1. 1Использовать глобальный axios во всех местах
  2. 2Добавлять interceptors при каждом рендере
  3. 3Считать, что catch покрывает все UX-сценарии
  4. 4Не отменять запрос при смене фильтра или страницы
  5. 5Сразу рендерить HTML из ответа через dangerouslySetInnerHTML
  6. 6Показывать один общий toast для любой ошибки

Если вас просят привести практический пример использования Axios, не ограничивайтесь axios.get. Покажите, что умеете строить безопасный слой API: отдельный instance, единый формат ошибок, отмена лишних запросов, понятные состояния UI и аккуратная работа с токеном.

Отдельно проговорите границу ответственности. Axios может добавить заголовок Authorization, но не должен хранить серверные секреты в браузере. Любой ключ, который попал в клиентский JavaScript, можно увидеть. Такие секреты должны жить на сервере.

Ответ от API тоже не становится безопасным только потому, что пришел через Axios. Не рендерите внешние строки как HTML без санитайза. Если API-клиент используется в SSR, не читайте window, localStorage или cookies на уровне модуля без проверки окружения. Иначе можно получить hydration mismatch или падение на сервере.

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

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

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

  1. 1

    Называть Axios магической обработкой ошибок

    Axios помогает тем, что по умолчанию отправляет статусы вне 2xx в catch, но не решает UX за вас. Нужно различать error.response, error.request и ошибку конфигурации. Иначе пользователь увидит один общий сбой вместо понятного действия.
  2. 2

    Ставить interceptors в компоненте без cleanup

    Если регистрировать interceptor при каждом рендере или маунте, обработчики могут дублироваться. В итоге один запрос получит несколько одинаковых заголовков или несколько раз запустит refresh token. Безопаснее настраивать клиент в отдельном модуле или удалять interceptor через eject.
  3. 3

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

    В UI пользователь может быстро менять фильтры, маршрут или поисковую строку. Старый ответ может прийти позже нового и перезаписать актуальные данные. Передавайте signal из AbortController и не показывайте отмену как ошибку.
  4. 4

    Сравнивать Axios и fetch слишком категорично

    Фраза "Axios всегда лучше fetch" звучит слабо. Для простого запроса fetch нормален, потому что он встроен в платформу. Axios лучше защищать конкретными требованиями: общий клиент, interceptors, timeout, удобная обработка JSON и ошибок.
  5. 5

    Хранить секреты в клиентских заголовках

    Заголовки Axios в браузере видны пользователю. Они не подходят для приватных серверных ключей. На фронтенде можно отправлять пользовательский access token по выбранной схеме, но секреты сервиса должны оставаться на бэкенде. Иначе это превращается в утечку доступа.
  6. 6

    Доверять данным ответа без проверки

    Axios может распарсить JSON, но не доказывает, что поля имеют нужный тип и безопасны для рендера. Если API вернул неожиданный формат, UI может упасть или показать неверное состояние. Если вставить строку из ответа как HTML, можно получить XSS. Безопаснее валидировать критичные поля и рендерить текст как текст.

Follow-up

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

Короткие ответы на вопросы, которыми проверяют понимание Axios, HTTP-ошибок и безопасного API-слоя во фронтенде.

Живые ответы

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

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

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

Содержание