Optimizing API Requests with Axios: Interceptors and Advanced Error Handling
Tags: react, javascript, axios, webdev
Published: 2024-01-03 13:05:32

## Table Of Contents
* [Introduction](#introduction)
* [Why Axios is Popular](#why-axios-is-popular)
* [Getting started with axios](#getting-started-with-axios)
* [Complete source code](#source-code)

<a name="introduction"></a>
Unlock the true potential of API communication in your projects! Let's delve into Axios, the versatile HTTP client, and explore how to elevate your request management with interceptors and robust error handling.

Axios and the native Fetch API are both tools for making HTTP requests in JavaScript, but they have some key differences. Here's a comparison that highlights why Axios is popular and how it differs from the native Fetch API:

## 1. Ease of Use and Syntax:
   - Axios: Provides a simple and consistent API with a clean syntax. Its methods return Promises, making it easy to chain and handle asynchronous operations.
   - Fetch API: While powerful, has a more verbose syntax, and handling different HTTP methods or headers may require additional boilerplate code.

## 2. Handling JSON Data:
   - Axios: Automatically parses JSON responses, simplifying the process of working with JSON data.
   - Fetch API: Requires manually calling the .json() method on the response to extract JSON data.

## 3. Interceptors:
   - Axios: Allows the use of interceptors, enabling you to intercept and modify HTTP requests or responses globally before they reach the .then() or .catch() block.
   - Fetch API: Doesn't have built-in interceptors, so achieving similar functionality requires additional code and handling at each usage point.

## 4. Error Handling:
   - Axios: Has robust error handling and automatically rejects promises on HTTP error status (e.g., 404 or 500).
   - Fetch API: Requires checking the ok property of the response manually, and errors are not automatically thrown.

### Why Axios is Popular: <a name="why-axios-is-popular"></a>
- Convenience: Axios offers a developer-friendly interface with clear syntax, making it easy to work with.
- Feature-Rich: Built-in features like interceptors, automatic JSON parsing, and request/response transformation contribute to its popularity.
- Consistent Behavior: Axios ensures consistent behavior across different browsers, addressing some inconsistencies present in the Fetch API.

## Getting started with Axios <a name="getting-started-with-axios"></a>

### 1. Install Axios:
Ensure you have Axios installed in your project. You can install it using npm or yarn:

```
npm install axios
// or
yarn add axios

```

### 2. Import & Create an Axios Instance:
Import Axios in your JavaScript file where you plan to make API requests & Create an Axios instance to set default configurations such as base URL, headers, etc. This can help in reusing the same configuration across multiple requests:

```
import axios from 'axios';

const api = axios.create({
  baseURL: 'https://api.example.com',
  headers: {
    'Content-Type': 'application/json',
    // Add any other common headers here
  },
});

```
### 3. Handle Request and Response Interceptors:
Axios allows you to use interceptors to globally handle requests and responses. This is useful for tasks such as adding headers, handling errors, etc.

```
// Request interceptor
api.interceptors.request.use(
  (config) => {
    // Modify the request config here (e.g., add authorization headers)
    return config;
  },
  (error) => {
    // Handle request errors
    return Promise.reject(error);
  }
);

// Response interceptor
api.interceptors.response.use(
  (response) => {
    // Modify the response data here
    return response;
  },
  (error) => {
    // Handle response errors
    return Promise.reject(error);
  }
);

```

### 4. Use Async/Await for Asynchronous Requests:
Utilize async/await syntax for cleaner and more readable asynchronous code:

```
async function fetchData() {
  try {
    const response = await api.get('/endpoint');
    // Handle the response data
  } catch (error) {
    // Handle errors
  }
}
```

### 5. Optimize Concurrent Requests:
If you have multiple requests that can be executed concurrently, consider using Promise.all to optimize performance:

```
async function fetchMultipleData() {
  try {
    const [data1, data2] = await Promise.all([
      api.get('/endpoint1'),
      api.get('/endpoint2'),
    ]);
    // Handle the data
  } catch (error) {
    // Handle errors
  }
}
```

### 6. Cancel Requests:
Axios supports request cancellation. This can be useful to prevent unnecessary requests, especially in scenarios where a user navigates away from a page before a request is completed:

```
const source = axios.CancelToken.source();

try {
  const response = await api.get('/endpoint', {
    cancelToken: source.token,
  });
  // Handle the response
} catch (error) {
  if (axios.isCancel(error)) {
    // Request was canceled
  } else {
    // Handle other errors
  }
}

// To cancel the request
source.cancel('Request canceled by the user');
```

> 

## Complete source code with success and error toast <a name="source-code"></a>
```
import { toast } from 'react-hot-toast';
import Axios from 'axios';

const axios = Axios.create({
  // Change it with your API baseURL
  baseURL: 'https://fakerapi.it/api/v1',
  headers: {
    'Content-Type': 'application/json',
  },
});

axios.interceptors.response.use(
  (response) => {
    const data = response?.data;

    console.log(data);

    if (data?.message && typeof data?.message === 'string') {
      toast.success(data.message);
    } else if (data?.status && typeof data?.status === 'string') {
      toast.success(data.status + ` - Status code: ${data.code}`);
    }

    // Change this according to your need
    return data.data;
  },
  (error) => {
    const data = error.response.data;

    if (data?.message && typeof data?.message === 'string') {
      toast.error(data.message);
    } else if (data?.status && typeof data?.status === 'string') {
      toast.error(data.status + ` - Status code: ${data.code}`);
    }

    return Promise.reject(data);
  }
);

axios.interceptors.request.use((config) => {
  let token = 'your-bearer-token';

  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  } else {
    // Handle the case where there is no token
    // You might want to redirect to the login page or take appropriate action
  }

  return config;
});

export default axios;
```

I have added my axios template code in the document, and here below are the links:
[GitHub Gist](https://www.0cb.tech/jbbch)
[Live code - StackBlitz](https://www.0cb.tech/fvopy)

{% embed https://stackblitz.com/edit/vitejs-vite-uqovqp?embed=1&file=src%2Flib%2Faxios.js %}