Axios interceptors: how to throw errors in the onFulfill?

Viewed 3950

I know that axios interceptors can handle bot ok and ko

axios.interceptors.response.use(
    // onFullfilled
    function(axios_response) {
       return axios_response;
    },

    // onRejected 
    function(axios_error) {
       console.log(axios_error);
       return Promise.reject(axios_error);
    }
)

My exact question is: how can I throw an error inside onRejected in a way to be able to handle then in the sibling onRejected?

I tried this

// onFullfilled
function(axios_response) {

    if (!axios_response.data) return axios_response;

    const { data } = axios_response;

    if (!data.status || !data.message) return axios_response;

    const { status, message } = data;

    console.log("status", status);
    console.log("message", message);

    if (status === "error") {
        return Promise.reject(axios_response);
    }


    return axios_response;
 },

But it's the wrong way, I think, because my rejection is not caught by the interceptor's onRejected handler.

2 Answers

You can write a fairly simple patch for axios.interceptors.response.use(), say axios.interceptors.response.use_().

Put the following in place after axios has been initialised:

axios.interceptors.response.use_ = function(onFullfilled, onRejected) {
    axios.interceptors.response.use(
        // onFullfilled
        function(response) {
            try {
                return onFullfilled(response);
            }
            catch(e) {
                return onRejected(e);
            }
        },
        // onRejected
        onRejected,
    )
};

The patch implements the same interface as the original .use(). After establishing the interceptions with .use_() instead of .use(), if your onFullfilled() throws (deliberately or othwewise), the same onRejected handler will be called as if a rejection had been intercepted.

That's the essence of it anyway.

If there's a possibility that either of the handlers will use keyword this, then the intended this will need to be specified with Function​.prototype​.call() :

axios.interceptors.response.use_ = function(onFullfilled, onRejected) {
    axios.interceptors.response.use(
        // onFullfilled
        function(response) {
            try {
                return onFullfilled.call(this, response);
            }
            catch(e) {
                return onRejected.call(this, e);
            }
        },
        // onRejected
        onRejected
    )
};

Make sure you return the Promise.rejct:

this.http.interceptors.response.use(async function (response: AxiosResponse<BaseApiResponse, any>) {
          
          if(response.data.code !== ApiCode.OPERATION_SUCCES) {
              return Promise.reject(response.data);
          }
          
          return response;

      }, function (error) {
          return Promise.reject(error);
}); 
Related