前端无感刷新token最佳方案

无感刷新token方案通常有三种,定时器刷新、根据过期时间刷新和后端返回过期状态码刷新。

定时器刷新:鬼才才会用这种方式。

根据过期时间刷新:万一用户设备的时间跟服务器时间不一样就傻眼了。

最直白最有效的方式一定是根据后端返回的状态码去刷新token。

但是这里有一个坑,如果只是简单的在请求拦截中进行逻辑判断,那你就掉进这个坑里了。

假如是在某种条件下,一次性调用多个接口。比如页面初始化时一次性向后端调了3个接口,3个接口返回的都是token过期的状态码,就会去调3次刷新token的接口,3次刷新token接口完事后,再去掉3次原来的接口,这一套下来,9次请求出去了,显然不合适。

实现思路:定义一个队列,以及一个消息状态,当第一个请求回来时,返回的是(424)token过期的状态码,则将这个消息状态设为true,后续所有的424请求,都放在这个队列中,同时,执行刷新token操作,当token刷新完成后,根据这个队列的顺序,再依次将请求发出。

这里以vue+axios为例

// 请求 响应拦截
import axios from 'axios'
import store from '@/store'
import { refreshToken} from '@/utils/auth'

const service = axios.create({
  baseURL: '/api',
  timeout: 5000
})

let isRefreshing = false
let requests = []

// 请求拦截器
service.interceptors.request.use(
    ...
)

// 响应拦截器
service.interceptors.response.use(
  response => {
    ...
  },
  async error => {
    const { status, data } = error.response
    if (status === 401) {
     // token过期
    } else if (status === 424) {
      // 重新登录时触发
      if (!isRefreshing) {
        isRefreshing = true
        await refreshToken() // 自行定义刷新token的方法
        requests.forEach(e => e())
        requests = []
        isRefreshing = false
        error.config.headers.Authorization = `Bearer ${store.state.token.access_token}`
        const firstApi = await service(error.config)
        return Promise.resolve(firstApi)
      } else {
        return new Promise(resolve => {
          requests.push(() => {
            error.config.headers.Authorization = `Bearer ${store.state.token.access_token}`
            return resolve(service(error.config))
          })
        })
      }
    } else {
      // 常规异常时触发
    }
  }
)

export default service

注意:只能在响应拦截中去处理,不能在请求拦截中处理。理论上在请求第一个的时候发现这个token已过期,后续的请求就可以拦截,减少请求次数,但是后端返回的速度一定比你前处理的要慢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值