axios - 同时发起多个请求时,token刷新的问题

要求:
  • 当用户发起一个请求时,判断token是否已过期,若已过期则先调refreshToken接口,拿到新的token后再继续执行之前的请求。
  • 这个问题的难点:当同时发起多个请求,而刷新token的接口还没返回,此时其他请求该如何处理?
方法
  • 拦截返回后的数据(用axios的响应拦截器):先发起请求,接口返回过期后,先刷新token,再进行一次重试。

import axios from 'axios'

// 从 localStorage 中获取token
const getLocalToken = () => window.localStorage.getItem('token')

// 创建axios实例
const instance = axios.create({
	baseURL: '/api',
	timeout: 5000,
	headers: {
		'X-Token': getLocalToken() // 创建实例的时候,会执行一次
	}
})

instance.setToken = (token) => {
	// 更新axios默认配置项中headers的token
	instance.defaults.headers['X-Token'] = token
	// 将新的token保存到localStorage
	window.localStorage.setItem('token', token)
}

const refreshToken = () => {
	return instance.post('/refreshtoken').then(res => res.data)
}

* `isRefreshing`:避免同时发送多个刷新token的请求
let isRefreshing = false

* `重试队列`,每一项将是一个待执行的函数形式
let requestList = []

* `响应拦截器`
instance.interceptors.response.use(
	response => {
		const { code } = response.data
		`code等于1234时,表示token过期了,此时需要刷新token`
		if (code === 1234) {
			const config = response.config
			
			`如果,未正在刷新token`
			if (!isRefreshing) {
				isRefreshing = true
				// 刷新token
				return refreshToken()
				  .then(res => {
						const { token } = res.data
						instance.setToken(token)
						config.headers['X-Token'] = token
						config.baseURL = '' // url已经带上了/api,避免出现/api/api的情况
						
						// 遍历`requestList`中的请求,使用 `新的token` 重新发送它们
						requestList.forEach(item => item(token))
						// 重试完后,清空这个队列
						requestList = []
						return instance(config)
						
				  }).catch(err => {
					    console.error('refreshToken-error =>', err)
					    window.location.href = '/'	    
				  }).finally(() => {
					    // 无论成功还是失败,都将isRefreshing设置为false
					    isRefreshing = false
				  })
			} else {
				`如果,正在刷新token`
				return new Promise((resolve) => {
					// 将resolve放进队列,用一个函数形式来保存,等token刷新后再执行
					requestList.push((token) => {
						config.baseURL = ''
						config.headers['X-Token'] = token
						resolve(instance(config))
					})
				})
			}
		}
		
		`code不等于1234时,直接返回response`
		return response
	},
	
	error => {
		return Promise.reject(error)
	}
)

  export default instance


  • 20
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值