前端实现无感刷新token

1.在axios 返回拦截器中实现
代码如下

const service = axios.create({
  baseURL:import.meta.env.VITE_API_BASEPATH, // api 的 base_url
  timeout: 600000, // 请求超时时间
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
    'Sys-Code': 'SRM'
  }
})

// response 拦截器
service.interceptors.response.use(
  response => {
    tryHideFullScreenLoading();
    const res = response.data
    if (response.status === 200 && response.config.responseType === 'blob' || response.config.responseType === 'arraybuffer') { // 文件类型特殊处理
      if (response.headers['content-disposition'] || (response.headers['content-type'] && response.headers['content-type'].indexOf('application/pdf') != -1)) {
        return response
      } else {
        const resultBlob = new Blob([response.data], { type: 'application/json' })
        const fr = new FileReader()
        fr.onload = function() {
          const result = this.result ? JSON.parse(this.result) : '{}'
          if (result.msg) {
            errorMessage(result.msg, result.code == 1 ? 'success' : 'error')
          }
        }
        fr.readAsText(resultBlob)
      }
    } else if (res.code != 0) {
      // 302	登录已失效
      if (res.code === 302) {
        if (res.data && res.data.extra === 1) {
          confirmMessage(`您的账号${res.data.extraTime}在别处登录。如非本人操作,则密码可能已泄漏,建议修改密码`)
        } else {
          clearCacheEnterLogin()
        }
      } 
      else if(res.code === '000000000001'){
        if (res.msg) {
          let newMsg = res.msg.replace(/\n/g,'<br/>')
          errorMessage(newMsg,'error',true)
        }
        return res
      }else if(res.code ==='3000300100302'){
       
        const config = response.config
        const refreshToken = getLocalStorage('Refresh-Token');
        if(config.url==='/saas/auth/account/refreshToken'){
          isRefreshToken = false
          errorMessage("登录无效,请重新登录")
          delLocalStorage("Access-Token");
          delLocalStorage("Refresh-Token");
          router.push({ path: "/login" });
          return Promise.reject(res)
        }
        if(!isRefreshToken){
          isRefreshToken=true;
         return refreshTokenByServer({refreshToken:refreshToken}).then((res:any) => {
        if(res && res.code==="0"){
         setLocalStorage("Access-Token", res.data.accessToken);
         setLocalStorage("Refresh-Token", res.data.refreshToken);
         // token 刷新后将数组的方法重新执行
         requests.forEach((cb) => cb(res.data.accessToken))
         requests = [] // 重新请求完清空
        
         config.headers["Access-Token"]=res.data.accessToken;
         config.headers["Refresh-Token"]=res.data.refreshToken;
         return service(config);
        }
       })
       .catch((err) => {
        errorMessage("登录无效,请重新登录")
        delLocalStorage("Access-Token");
        delLocalStorage("Refresh-Token");
        router.push({ path: "/login" });
        return Promise.reject(err)
        }).finally(() => {
          isRefreshToken = false
        })
        }
        else {
          // 返回未执行 resolve 的 Promise
          return new Promise(resolve => {
            // 用函数形式将 resolve 存入,等待刷新后再执行
            requests.push((accessToken:any) => {
              resolve(service(config))
            })
          })
        }
      
      }
      else if(res.code ==='3000300100301'){
        errorMessage("登录无效,请重新登录")
        delLocalStorage("Access-Token");
        delLocalStorage("Refresh-Token");
        router.push({ path: "/login" });
      }
      else {
        if (res.msg) {
          errorMessage(res.msg)
        }
      }
      return Promise.reject(res)
    } 
    return res
  },
  error => {
    tryHideFullScreenLoading();
    if (error.response) {
      const response = error.response
      if (response.status == 500) {
        errorMessage('网络错误,请检查您的网络')
      } else if (response.data && response.data.msg) {
        errorMessage(response.data.msg)
      }
    }
    return Promise.reject(error)
  }
)
posted @ 2022-12-26 10:13  火龙果呀  阅读(390)  评论(0)    收藏  举报