axios 实现 无感刷新方案

  1. 实现思路
    1. 首次登录前端通过接口获取到两个 token;分别是 accessToken、refreshToken;
    2.  accessToken:正常请求需要传递的  token ;
    3. refreshToken:当某个请求 401 ,就可以通过 refreshToken 获取到新的 accessToken
    4.  特殊场景:如果 refreshToken 也过期了 ,那就默认跳回 登录页,重新登录,就类似  七天免登录的场景、过了 第七天,refreshToken  也就过期了;
  2. 代码
    1. 
      import axios from "axios";
      import { refreshToken } from "../api/index"; //刷新token的api
      let isRefreshToken = false; //是否正在进行刷新token
      let requestList = []; // 请求队列
      
      const request = axios.create({
        baseURL: "/api",
        timeout: 10000,
      });
      
      // 请求拦截器
      request.interceptors.request.use(
        (config) => {
          let headerToken = localStorage.getItem("acc_token");
          // 设置请求头
          config.headers.Authorization = `Bearer ${headerToken}`;
          return config;
        },
        (error) => {
          // 请求错误时做些事
          return Promise.reject(error);
        }
      );
      
      // 响应拦截器
      request.interceptors.response.use(
        async (response) => {
          // 401 代表token过期,需要刷新token
          if (response.data.code == 401) {
            // 这里可以加入判断,判断 refreshToken 也过期了,直接 router.push 回登录页
            // if () {
            // router.push('/login')
            // }
            if (!isRefreshToken) {
              isRefreshToken = true;
              let res = await refreshToken(); // 刷新 token 的接口
              isRefreshToken = false;
              localStorage.setItem("acc_token", res.data.accToken);
              //   重发请求队列请求
              requestList.forEach((callback) => {
                callback();
              });
              requestList = [];
      
              let currentRequest = await request(response.config);
              return currentRequest;
            } else {
              // 将并发的请求,通过回调函数暂存起来,当token 刷新之后,在进行请求
              return new Promise((resolve) => {
                requestList.push(() => {
                  resolve(request(response.config));
                });
              });
            }
          }
          return response;
        },
        (error) => {
          return Promise.reject(error);
        }
      );
      
      export default request;

你可能感兴趣的:(前端)