Axios 无感刷新

DONG HAO
2023-12-27 / 0 评论 / 23 阅读 / 正在检测是否收录...
token无感刷新的原理很简单,使用双token,分别为accessTokenrefreshToken,正常都是携带accessToken进行验证。当返回状态码表示token过期时,再携带refreshToken重新获取accessToken,然后重新携带accessToken发起请求。
// axiox.ts
import axios from "axios";
import { AxiosRetry } from './axiosClass'

axios.defaults.baseURL='http://127.0.0.1:3000'

// 添加请求拦截器
axios.interceptors.request.use(
  function (config) {
    // 在发送请求之前做些什么
    // 在请求头中添加token
    config.headers.Authorization = localStorage.getItem("accessToken");
    if (config.url == "/refreshToken") {
      config.headers.Authorization = localStorage.getItem("refreshToken");
    }
    return config;
  },
);


/**先到拦截器*/
axios.interceptors.response.use(res => {
  if (res.status != 200) {    
    return Promise.reject(res.data);
  }
  return Promise.resolve(res.data)
});

const axiosRetry = new AxiosRetry({
  onSuccess: (res) => {
    let { accessToken } = res.data
    localStorage.setItem("accessToken", accessToken);
  },
  onError: () => {
    console.log('refreshToken过期,需要重新登录');
  },
});


export const request = (url: string) => {
  return axiosRetry.requestWrapper(() => {
    return axios({
      method: "get",
      url: `${url}`,
    })
  });
}
// axiosClass.ts
import { Axios } from 'axios';
import axios from 'axios';

export class AxiosRetry {
  private fetchNewTokenPromise: Promise<any> | null = null;
  private onSuccess: (res: any) => any;
  private onError: () => any;

  constructor({
    onSuccess,
    onError,
  }: {
    onSuccess: (res: any) => any;
    onError: () => any;
    }) {
    this.onSuccess = onSuccess;
    this.onError = onError;
  }

  /** 发送请求*/
  requestWrapper<T>(request: () => Promise<T>): Promise<T> {
    return new Promise((resolve, reject) => {
      /** 将请求接口的函数保存*/
      const requestFn = request;
      return request().then((res) => {
        //拦截器处理后的数据
        resolve(res);
      }).catch(err => {
        //token过期或者没有token    
        if (err.response.status === 401) {
          if (!this.fetchNewTokenPromise) {
            this.fetchNewTokenPromise = this.fetchNewToken();
          }
          this.fetchNewTokenPromise.then(() => {
            return requestFn();
          }).then((res) => {
            resolve(res);
            this.fetchNewTokenPromise = null;
          }).catch((err) => {
            reject(err);
            this.fetchNewTokenPromise = null;
          });
        } else {
          reject(err);
        }
      });
    });
  }

  // 获取新的token
  fetchNewToken() {
    return axios({
      method: "post",
      url: `/refreshToken`,
    }).then((res) => {
      this.onSuccess(res)
    }).catch((err) => {
      this.onError();
      //表示refreshToken过期,需要重新登录
      if (err.response.status === 401) {
        return Promise.reject(
          new Error("refreshToken过期,需要重新登录")
        );
      }
      //表示发生了其他错误
      else {
        return Promise.reject(err); 
      }
    })
  }
}

0

评论 (0)

取消