Mastering Axios Interceptors
Axios is a powerful HTTP client for JavaScript that allows you to easily interact with APIs. One of its most useful features is interceptors, which let you run custom code before a request is sent or after a response is received. This guide will walk you through everything you need to know about Axios interceptors, including their types and several practical use cases.
Types of Axios Interceptors
Request Interceptors
Request interceptors are executed before a request is sent. They allow you to modify the request configuration or handle errors. The config
parameter represents the request configuration object, which includes details like the URL, method, headers, and data.
axios.interceptors.request.use(
function (config) {
// Modify the request config here
return config
},
function (error) {
// Handle the request error here
return Promise.reject(error)
},
)
The shape of the config
object typically includes:
url
: The URL of the request.method
: The HTTP method (GET, POST, etc.).headers
: An object representing the request headers.params
: URL parameters.data
: The payload for POST/PUT requests.
For example:
{
"url": "/api/data",
"method": "get",
"headers": {
"Authorization": "Bearer token"
},
"params": {
"id": 1
},
"data": {
"name": "John Doe"
}
}
Response Interceptors
Response interceptors are executed after a response is received. They allow you to modify the response data or handle errors.
axios.interceptors.response.use(
function (response) {
// Modify the response data here
return response
},
function (error) {
// Handle the response error here
return Promise.reject(error)
},
)
Use Cases for Axios Interceptors
1. Adding Authorization Headers
You often need to include an authorization token in your request headers for authenticated API calls. Request interceptors can be used to automatically attach this token.
axios.interceptors.request.use(
function (config) {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
},
function (error) {
return Promise.reject(error)
},
)
2. Handling Unauthorized Responses
You might want to handle unauthorized responses globally by redirecting the user to a login page or displaying an error message.
axios.interceptors.response.use(
function (response) {
return response
},
function (error) {
if (error.response && error.response.status === 401) {
// Redirect to login page or show an error message
window.location.href = '/login'
}
return Promise.reject(error)
},
)
3. Logging Requests and Responses
For debugging purposes, it's often useful to log details of requests and responses. You can use interceptors to log this information.
axios.interceptors.request.use(
function (config) {
console.log('Request:', config)
return config
},
function (error) {
console.error('Request error:', error)
return Promise.reject(error)
},
)
axios.interceptors.response.use(
function (response) {
console.log('Response:', response)
return response
},
function (error) {
console.error('Response error:', error)
return Promise.reject(error)
},
)
4. Retrying Failed Requests
In case of a failed request, you might want to retry it automatically. This can be achieved using response interceptors. In this example, we create a separate axiosInstance
to avoid modifying the default Axios instance, providing better isolation and control over the retry logic.
We also set a fixed number of retry attempts to avoid an infinite loop, which is a bad practice.
import axios from 'axios'
const axiosInstance = axios.create() // Create a separate Axios instance
const MAX_RETRY_ATTEMPTS = 3 // Set a fixed number of retry attempts
axiosInstance.interceptors.response.use(
function (response) {
return response
},
function (error) {
const config = error.config
if (!config.__retryCount) {
config.__retryCount = 0
}
if (config.__retryCount < MAX_RETRY_ATTEMPTS) {
config.__retryCount += 1
return axiosInstance(config)
}
return Promise.reject(error)
},
)
In this example:
- We create an
axiosInstance
to encapsulate the retry logic separately. - We define a constant
MAX_RETRY_ATTEMPTS
to limit the number of retry attempts to 3. - We use
config.__retryCount
to track the number of retry attempts for each request. - The interceptor retries the request if the retry count is less than the maximum allowed attempts.
5. Displaying Toast Notifications for Success and Failure
You can show toast notifications to inform users about the success or failure of API calls using interceptors.
import axios from 'axios'
import { toast } from 'react-toastify'
// Set up request interceptor
axios.interceptors.request.use(
function (config) {
return config
},
function (error) {
toast.error('Request failed')
return Promise.reject(error)
},
)
// Set up response interceptor
axios.interceptors.response.use(
function (response) {
toast.success('Request succeeded')
return response
},
function (error) {
toast.error('Request failed')
return Promise.reject(error)
},
)
Conclusion
Axios interceptors provide a powerful way to handle global concerns like adding authorization headers, handling errors, logging, retrying requests, and displaying notifications. By leveraging these interceptors, you can make your code more modular, maintainable, and easier to debug. Experiment with the examples provided and incorporate interceptors into your projects to take full advantage of Axios's capabilities.
Remember, interceptors can be a double-edged sword if not used carefully. Always ensure that the logic within interceptors is performant and error-free to avoid unexpected issues in your applications.