![c9deb743e8994b64229b87ace118953b.png](https://i-blog.csdnimg.cn/blog_migrate/6b52afa6454ed2e88c3f13431a071219.jpeg)
前言
前段时间写了篇文章《axios如何利用promise无痛刷新token》,陆陆续续收到一些反馈。发现不少同学会想要从在请求前拦截
的思路入手,甚至收到了几个邮件来询问博主遇到的问题,所以索性再写一篇文章来说说另一个思路的实现和注意的地方。过程会稍微啰嗦,不想看实现过程的同学可以直接拉到最后面看最终代码。
PS:在本文就略过一些前提条件了,请新同学阅读本文前先看一下前一篇文章《axios如何利用promise无痛刷新token》。
前提条件
前端登录后,后端返回token
和token有效时间段tokenExprieIn
,当token过期时间到了,前端需要主动用旧token去获取一个新的token,做到用户无感知地去刷新token。
PS:
tokenExprieIn
是一个单位为秒的时间段,不建议使用绝对时间,绝对时间可能会由于本地和服务器时区不一样导致出现问题。
实现思路
方法一
在请求发起前拦截每个请求,判断token的有效时间是否已经过期,若已过期,则将请求挂起,先刷新token后再继续请求。
方法二
不在请求前拦截,而是拦截返回后的数据。先发起请求,接口返回过期后,先刷新token,再进行一次重试。
前文已经实现了方法二,本文会从头实现一下方法一。
实现
基本骨架
在请求前进行拦截,我们主要会使用axios.interceptors.request.use()
这个方法。照例先封装个request.js
的基本骨架:
import axios from 'axios'
// 从localStorage中获取token,token存的是object信息,有tokenExpireTime和token两个字段
function getToken () {
let tokenObj = {}
try {
tokenObj = storage.get('token')
tokenObj = tokenObj ? JSON.parse(tokenObj) : {}
} catch {
console.error('get token from localStorage error')
}
return tokenObj
}
// 给实例添加一个setToken方法,用于登录后方便将最新token动态添加到header,同时将token保存在localStorage中
instance.setToken = (obj) => {
instance.defaults.headers['X-Token'] = obj.token
window.localStorage.setItem('token', JSON.stringify(obj)) // 注意这里需要变成字符串后才能放到localStorage中
}
// 创建一个axios实例
const instance = axios.create({
baseURL: '/api',
timeout: 300000,
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
}
})
// 请求发起前拦截
instance.interceptors.request.use((config) => {
const tokenObj = getToken()
// 为每个请求添加token请求头
config.headers['X-Token'] = tokenObj.token
// **接下来主要拦截的实现就在这里**
return config
}, (error) => {
// Do something with request error
return Promise.reject(error)
})
// 请求返回后拦截
instance.interceptors.response.use(response => {
const { code } = response.data
if (code === 1234) {
// token过期了,直接跳转到登录页
window.location.href = '/'
}
return response
}, error => {
console.log('catch', error)
return Promise.reject(error)
})
export default instance
与前文略微不同的是,由于方法二不需要用到过期时间,所以前文localStorage中只存了token一个字符串,而方法一这里需要用到过期时间了,所以得存多一个数据,因此localStorage中存的是Object
类型的数据,从localStorage中取值出来需要JSON.parse
一下,为了防止发生错误所以尽量使用try...catch
。