多个请求同时发起情况下的token无痛刷新

本文章主要记录个人在项目开发过程中遇到的多个请求同时发起,失败的请求重试的问题。参照网上许多token无痛刷新案例,根据自己项目做了一些补充。需要明白的是在异步请求的情况下,多个请求同时发起,如果token无效,则必然这几个请求都需要重试,当我们收到第一个401响应(表示token过期)就拿刷新token去刷新,然后重试请求,如果token更新前所有的401响应都已经放在了队列中,可以直接参考该文章:前端axios无痛刷新token,还有一种情况是在我们成功刷新了token过后部分token刷新前响应才响应回来,这就需要我们多做一次判断:

 //非首次收到401响应的请求
        const reqToken = config.headers.Authorization//该请求发起时携带的token
        const token =getToken()
        //token已经更新就重试请求
        if (reqToken !== token) {
          config.headers['Authorization'] = token
          return service(config)
        } else {
          //token未更新则放在队列中,更新后再释放
          return new Promise((resolve) => {
            requests.push((rToken) => {
              config.headers['Authorization'] =rToken
              resolve(service(config))
            })
          })
        }

完整代码如下:

service.interceptors.response.use(
  response => {
    const { status } = response.data
    //当后端返回状态码为401,代表token过期:token过期首先通过刷新token进行刷新,如果刷新成功则失败请求重试,如果刷新失败就重新登录
    if (status === 401) {
      const config = response.config
      if (!isRefreshing) {
        isRefreshing = true;
        return reToken(getReToken()).then((res) => {
          const { accessToken, refreshToken } = res.data
          //更新浏览器token和retoken
          setToken(accessToken)
          setReToken(refreshToken)
          //当前请求重新设置token
          config.headers['Authorization'] =  accessToken
          //token刷新前的401请求队列重试
          if (requests.length > 0) {
            requests.forEach(cb => cb(accessToken))
            requests = []
          }
          return service(config)
        }).catch((error) => {
          requests = []
          //token刷新失败,只能去登录
        }).finally(() => {
          isRefreshing = false
        })

      } else {
        //非首次收到401响应的请求
        const reqToken = config.headers.Authorization//该请求发起时携带的token
        const token = getToken()
        //token已经更新就重试请求
        if (reqToken !== token) {
          config.headers['Authorization'] = token
          return service(config)
        } else {
          //token未更新则放在队列中,更新后再释放
          return new Promise((resolve) => {
            requests.push((rToken) => {
              config.headers['Authorization'] = rToken
              resolve(service(config))
            })
          })
        }
      }
    }
    return response.data
  },
  error => {
    Message({
      message: error.message,
      type: 'error'
    })
    return Promise.reject(error)
  }
)

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值