admin管理员组

文章数量:1347815

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

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);
      }
    }
  }
);
Share Improve this question asked Apr 6, 2023 at 7:38 DevRohanDevRohan 811 silver badge5 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 11

I think your solution is a little too plicated. I'd simply store the Promise returned by refreshToken() untill it is fulfilled and let all ining 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.

Thankyou I found solution ..

import { setAccessToken } from "../Store/authSlice";
import store from "../Store";
import { normalRoute } from "./axios";

// for multiple requests
let isRefreshing = false;
let failedQueue = [];

const processQueue = (error, token = null) => {
  failedQueue.forEach((prom) => {
    if (error) {
      prom.reject(error);
    } else {
      prom.resolve(token);
    }
  });

  failedQueue = [];
};

const interceptor = (axiosInstance) => (error) => {
  const _axios = axiosInstance;
  const originalRequest = error.config;

  if (error.response.status === 401 && !originalRequest._retry) {
    if (isRefreshing) {
      return new Promise(function (resolve, reject) {
        failedQueue.push({ resolve, reject });
      })
        .then((token) => {
          originalRequest.headers["Authorization"] = "Bearer " + token;
          return _axios.request(originalRequest);
        })
        .catch((err) => {
          return Promise.reject(err);
        });
    }

    originalRequest._retry = true;
    isRefreshing = true;

    return new Promise(async (resolve, reject) => {
      try {
        const response = await normalRoute.post("/users/refresh");
        _axios.defaults.headers.mon["Authorization"] =
          "Bearer " + response.data.accessToken;
        originalRequest.headers["Authorization"] = "Bearer " + response.data.accessToken;
        processQueue(null, response.data.accessToken);
        resolve(_axios(originalRequest));
      } catch (err) {
        processQueue(err, null);
        reject(err);
      } finally {
        isRefreshing = false;
      }
    });
  }

  return Promise.reject(error);
};

export default interceptor;
import axios from "axios";
import interceptor from "./authInterceptor";

const privateInstance = axios.create({
  baseURL: "http://localhost:5000/api/v1",
});

privateInstance.defaults.withCredentials = true;

privateInstance.interceptors.response.use(undefined, interceptor(privateInstance));

export default privateInstance;

本文标签: javascriptHow to run axios interceptor once for multiple request on 401 errorStack Overflow