Skip to content
Advertisement

Axios catch not working when used with a customer interceptor

I am using interceptor that refreshes the access token upon a status code of 401 but my catch has stopped working upon any other error codes such as 400

request.js

import axios from 'axios'

const axiosApiInstance = axios.create()

axiosApiInstance.interceptors.response.use(
    (response) => {
      return response
    },
    (error) => {
      return new Promise((resolve) => {
        const originalRequest = error.config
        const refreshToken = localStorage.getItem("refresh")
        if (error.response && error.response.status === 401 && error.config && !error.config.__isRetryRequest && refreshToken) {
          originalRequest._retry = true
  
          const response = fetch('http://127.0.0.1:8000/api/token/refresh/', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({
              refresh: refreshToken,
            }),
          })
            .then((res) => res.json())
            .then((res) => {
              localStorage.setItem("access", res.access) 
              originalRequest.headers['Authorization'] = 'Bearer ' + res.access
              return axios(originalRequest)
            })
          resolve(response)
        }
        return Promise.reject(error)
      })
    },
  )

  export default axiosApiInstance

Advertisement

Answer

You need to pass a second argument to your callback to new Promise called reject and then reject the promise using that function instead of Promise.reject.

I can’t verify without testing, and that’s a bit difficult to set up right now, but it looks very much like you’re not properly rejecting the promise that you’re returning from the error callback. If you can confirm that the promise is never resolved or rejected in the case of a 400, that would help confirm my suspicion. Try making this change, though:

The arguments to your new Promise callback:

      return new Promise((resolve) => {

becomes

      return new Promise((resolve, reject) => {

and later to reject, instead of

        return Promise.reject(error)

just do this

        reject(error) // return does nothing here, can be omitted

Edit:

Although, a very good point by someone that this is a promise anti-pattern. You’re creating a new Promise for no reason.

import axios from 'axios'

const axiosApiInstance = axios.create()

axiosApiInstance.interceptors.response.use(
    (response) => {
      return response
    },
    (error) => {
        const originalRequest = error.config
        const refreshToken = localStorage.getItem("refresh")
        if (error.response && error.response.status === 401 && error.config && !error.config.__isRetryRequest && refreshToken) {
            originalRequest._retry = true

            return fetch('http://127.0.0.1:8000/api/token/refresh/', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                refresh: refreshToken,
            }),
            })
            .then((res) => res.json())
            .then((res) => {
                localStorage.setItem("access", res.access) 
                originalRequest.headers['Authorization'] = 'Bearer ' + res.access
                return axios(originalRequest)
            })
        }
        return Promise.reject(error)
    },
  )

  export default axiosApiInstance

Should be something like this.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement