Search code examples
promiseaxiosinterceptor

Axios interceptors: how to throw errors in the onFulfill?


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.


Solution

  • 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
        )
    };