Axios: calling an HTTP API with shared configuration

Axios is an HTTP client that parses JSON, rejects on a failure status and gathers headers, timeout and token into one shared instance.
3 min read
Believemy logo

The first network call of a project fits in three lines. The twentieth drags along the same base address, the same authorization header and the same error handling, copied twenty times over.

Axios exists so that shared part gets written once.


Definition

Axios is an HTTP client library, usable in the browser and under Node.js alike. Every call returns a Promise, the JSON body arrives already parsed, and a failure status rejects the promise instead of fulfilling it.

JAVASCRIPT
import axios from "axios";

const api = axios.create({
  baseURL: "https://api.example.com",
  timeout: 5000,
  headers: { "X-Client": "believemy" },
});

const { data } = await api.get("/invoices/42");
console.log(data.amount);   // 19

The instance carries the base address, the timeout and the shared headers. Every other file writes nothing but the path, and a change of address touches a single place.


What sets it apart from fetch

TopicWith fetchWith Axios
404 statusThe promise fulfills, checking is on youThe promise rejects
JSON bodyAn explicit second stepAlready parsed in data
TimeoutWired up with an AbortControllerA timeout option
Shared settingsWritten by handOne shared instance
InstallationNothing, fetch() is built inA package to add

The table holds three columns because there are only three questions to ask: the topic, then what each of the two clients does about it. The first row is by far the most surprising one, a failure status going unnoticed with fetch whenever nobody tests response.ok.


Interceptors

An interceptor is a function called on every request or every response of the instance. That is where the authentication token, the logging trace or the shared reaction to an expired session belong.

JAVASCRIPT
api.interceptors.request.use((config) => {
  config.headers.Authorization = `Bearer ${readToken()}`;
  return config;
});

api.interceptors.response.use(
  (response) => response,
  (error) => {
    if (error.response?.status === 401) signOut();
    return Promise.reject(error);
  }
);
Good to know

The Optional chaining (?.) on error.response is not decorative: when the server does not answer at all, the property is absent and a direct read would raise a TypeError on top of the network error.


Frequently asked questions

Question

Is Axios justified now that fetch is everywhere?

For two or three isolated calls, no: fetch is built in, with no dependency to keep updated. On a project firing many requests at the same API, the shared instance and the interceptors save a whole file of repetitive code. Many teams also write their own wrapper around fetch, which amounts to rebuilding part of Axios.


Question

How is an error handled?

With a try around the call. The object received carries a response property when the server answered, and its status tells a 404 apart from a 500. When that property is missing, the request never reached its destination, and the message to display is not the same one.


Question

Can a request in flight be canceled?

Yes, by passing an AbortController signal in the call options. It is the same mechanism fetch uses, which spares learning two interfaces. The classic use case remains search-as-you-type, where every new letter must cancel the previous request.

Related terms

Discover our javaScript glossary

Every word of JavaScript explained simply: keywords, built-in objects, methods, errors and concepts. Clear definitions and examples that actually run, to learn and to troubleshoot.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.