方案一
思路:
后端需要返回一个token过期的时间,在请求发起前拦截每个请求,判断token的有效时间是否已经过期,如果已过期,则暂时将请求挂起,先刷新token后再继续请求。
前期思考:
- 返回过期时间是为了判断是否过期的,但是如果服务器时间和系统时间不一致呢?
- 如果同时发起多个请求时怎么办?
实现:
因为是在请求前进行拦截,所以这里用axios的axios.interceptors.request.use()
方法
首先,关于服务器时间和系统时间不一致的问题,我的解决方法是:
后端返回的过期时间应该是一个时间段,而不是绝对时间,这样就避免了二者时间不一致的问题。前端拿到token的有效时间后,在存到localStorage前,先依据系统时间转成绝对时间。
例如:当前时间是12点,有效时间是3600秒(1个小时),则存到localStorage的过期时间是13点的时间戳,使用时只需要判断这个绝对时间即可。
- 先不考虑复杂情况,正常接口请求
// 请求前先进行拦截
instance.interceptors.request.use((config) => {
//这里不单单是获取到token,还要一个token的过期时间,用来进行下面的判断
const tokenInfo = getToken()
/**
* 这里模拟一下tokenInfo的结构
* tokenInfo:{
* token:'fdasfeffafdsfasfdasfdas',
* tokenExpireTime:'36000'
* }
*/
//这里先拿到token,给每个请求添加一个token请求头
config.headers['token'] = tokenInfo.token
// 注意:登录接口和刷新token接口是不需要token的
if (config.url.indexOf('/refreshToken') >= 0 || config.url.indexOf('/login') >= 0) {
return config
}
//这里是拦截的关键代码
if (tokenInfo.token && tokenInfo.tokenExpireTime) {
const now = Date.now()
if (now >= tokenInfo.tokenExpireTime<