Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run axios interceptor once for multiple request on 401 error?

I have setup for axios and react-query together for my food application . I want to implement refreshing token only once for more than 2 parallel request and retry all the pending failed request . I searched so many solutions on the web , tried them but none of them worked . Here is my code reference .

let isRefreshing = false;
let failedQueue = [];

async function refreshToken() {
  const response = await normalRoute.post("/users/refresh");
  return response.data.accessToken;
}

privateRoute.interceptors.response.use(
  (response) => response,
  async (error) => {
    if (error.response.status === 401) {
      failedQueue.push(error.config);
      if (!isRefreshing) {
        isRefreshing = true;
        const token = await refreshToken();
        store.dispatch(setAccessToken(token));

        const promsieArray = failedQueue.map((config) => {
          config.headers.authorization = `Bearer ${token}`;
          return privateRoute(config);
        });

        failedQueue = [];
        return Promise.resolve(promsieArray);
      }
    }
  }
);
like image 579
DevRohan Avatar asked Sep 19 '25 20:09

DevRohan


1 Answers

I think your solution is a little too complicated. I'd simply store the Promise returned by refreshToken() untill it is fulfilled and let all incoming 401s await the same Promise, then retrying.

let refreshPromise = null;
const clearPromise = () => refreshPromise = null;

async function refreshToken() {
  const response = await normalRoute.post("/users/refresh");
  return response.data.accessToken;
}

privateRoute.interceptors.response.use(
  undefined,
  async (error) => {
    const config = error.config;
    
    if (error.response.status === 401 && !config._retry) {
      config._retry = true;

      if (!refreshPromise) {
        refreshPromise = refreshToken().finally(clearPromise);
      }

      const token = await refreshPromise;
      config.headers.authorization = `Bearer ${token}`;

      return privateRoute(config);
    }
  }
);

And kill that Promise when it is fulfilled so that later 401s have a chance to refresh the token yet again.

like image 127
Thomas Avatar answered Sep 21 '25 11:09

Thomas