Back to Networking
Networking
easy
mid

Have you used Axios, and what are interceptors and when should you use them?

Axios is a promise-based HTTP client. Interceptors are hooks that run on every request before it's sent or every response before it resolves — used for attaching auth tokens, logging, global error handling, token refresh, and loading indicators. They centralize cross-cutting HTTP concerns.

6 min read·~10 min to think through

Axios is a promise-based HTTP client for the browser and Node — over fetch it adds automatic JSON parsing, request/response transforms, instance config, timeouts, upload/download progress, easier error handling, and interceptors.

What interceptors are

Interceptors are functions Axios runs automatically on every request or response passing through an instance — middleware for HTTP. Two kinds:

js
// Request interceptor — runs before the request is sent
api.interceptors.request.use(
  (config) => {
    config.headers.Authorization = `Bearer ${getToken()}`;
    return config;            // must return config
  },
  (error) => Promise.reject(error)
);

// Response interceptor — runs before the response/error reaches your code
api.interceptors.response.use(
  (response) => response,     // pass through / unwrap response.data
  (error) => {
    if (error.response?.status === 401) redirectToLogin();
    return Promise.reject(error);
  }
);

What they're used for

  • Auth — attach the access token to every request; on a 401, attempt a token refresh and retry the original request (queue concurrent requests during refresh).
  • Global error handling — map status codes to behaviors (401 → logout, 403 → forbidden page, 5xx → toast), so each call site doesn't repeat it.
  • Logging / monitoring — log every request/response, report failures.
  • Loading state — increment/decrement a global in-flight counter for a top-level spinner.
  • Headers / config — base URL, correlation ids, locale, content-type defaults.
  • Transforming — camelCase ↔ snake_case, unwrap response.data.
  • Retries — backoff retry on transient failures.

Why they matter

They centralize cross-cutting concerns. Without interceptors, every API call re-implements auth headers, error handling, and logging. With them, it's defined once on the instance.

js
const api = axios.create({ baseURL: "/api", timeout: 10000 });
// register interceptors once; every api.get/post inherits them

Gotchas / good practice

  • A request interceptor must return config (or a promise of it); a response interceptor must return the response or reject.
  • The token-refresh-and-retry flow is the classic tricky case — guard against infinite loops, and queue requests that arrive mid-refresh so they don't each trigger a refresh.
  • You can eject interceptors; order matters when you register several.
  • Modern note: many teams now wrap fetch (or use React Query's fetcher) and replicate this with a small client — but the interceptor concept (centralized request/response middleware) is the thing to understand.

How to answer

"Yes — Axios is a promise-based HTTP client; the feature I lean on most is interceptors. I use a request interceptor to attach the auth token and a response interceptor for global error handling and the 401 → refresh-and-retry flow, so cross-cutting HTTP concerns live in one place instead of every call site."

Follow-up questions

  • Walk through implementing token refresh in a response interceptor.
  • How do you avoid an infinite loop in a refresh interceptor?
  • What does Axios give you over fetch?
  • How would you handle concurrent requests that all get a 401 during a refresh?

Common mistakes

  • Forgetting to return config from a request interceptor.
  • A refresh interceptor that loops infinitely on repeated 401s.
  • Not queuing concurrent requests during a token refresh — each triggers its own.
  • Putting auth/error logic at every call site instead of in an interceptor.

Performance considerations

  • Interceptors run on every request/response — keep them light. The refresh-and-retry queue prevents a thundering herd of refresh calls.

Edge cases

  • Multiple requests failing with 401 simultaneously during refresh.
  • The refresh request itself failing.
  • Interceptor order when several are registered.
  • Request cancellation interacting with interceptors.

Real-world examples

  • An axios instance with a request interceptor for auth and a response interceptor doing 401 -> refresh -> retry with a request queue.
  • A global loading spinner driven by an in-flight counter incremented/decremented in interceptors.

Senior engineer discussion

Seniors describe interceptors as centralized HTTP middleware and go deep on the canonical hard case — token refresh with a request queue to avoid loops and herds. They note the must-return-config detail and acknowledge that the concept (request/response middleware) outlives the specific library, since many teams now wrap fetch.

Related questions