token无感刷新 | token自动刷新 | token过期

97 阅读1分钟

token刷新规则

token过期自动刷新,成功后刷新token,失败可去登录界面。

Axios的封装

  1. 发起token更新请求时,若有其它请求,利用promise将请求先挂起,并push到一个数组
  2. token请求返回结果后,再重新发起请求,执行push的数组
  3. 后端状态码为304表示token过期
import axios from 'axios';

// 创建一个 axios 实例
const service = axios.create({
  timeout: 5000,
});

let tokenUpdateing = false,//token是否处于更新中
  reqLists = [],//更新token时请求的队列 
  tokenStr = '';//token

// 请求拦截器
service.interceptors.request.use(config => {
  // 带上token发起请求
  tokenStr && (config.headers.auth = tokenStr);

  return config;
}, error => {
  // return error
  Promise.reject(error);
})

// 响应拦截器
service.interceptors.response.use(response => {
  const { statu } = response.data,
    { url, method, params } = response.config;
  // token过期
  if (statu === 304) {
    const reqConfig = { url, method, params };
    //  更新token中,先将请求配置push到reqLists,token更新完成后再重新发起请求
    if (tokenUpdateing === true) {
      //token更新中,将请求挂起
      return new Promise(resolve => {
        // token更新中,push请求 ,不push相同的请求
        const configStr = JSON.stringify(reqConfig);
        const findRepeat = reqLists.findIndex(val => val.id === configStr);
        if (findRepeat === -1) reqLists.push({id:configStr,callback:token=>{
          response.headers.auth = `${token}`;
          resolve(service(response.config));
        }});
      })
      // 开始更新token
    } else {
      tokenUpdateing = true;
      const uid = 6666;//用户id
      //向后端请求新token 
      const sendData = {
        url: `/api/updatetoken`,
        params: {
          uid
        }};
      return service(sendData).then((res)=>{
        const { token } = res.data;
        // token请求成功
        tokenStr = token;
        res.headers.auth = `${token}`;
        //token更新完成 ——> 重新发起请求
        reqLists.forEach(val => val.callback(token));
        reqLists = [];//清空请求队列 
        // 重新发起请求
        return service(response.config);
      }).catch(err=>{
        // token请求失败 可以去登录界面
        return Promise.reject(err);
      }).finally(()=>{
        tokenUpdateing = false;//关闭token更新 
      });
    }
  }
  return response && response.data;
}, error => {
  Promise.reject(error);
})

export default service;