1、request.js
import axios from 'axios'
import { setToken,setRefreshToken,getToken } from './token'
import { refreshToken,isRefreshRequest } from './refreshToken'
const ins = axios.create({
baseURL:'http://localhost:9527',
headers:{
Authorization:`Bearer ${getToken()}`
}
})
ins.interceptors.response.use(async (res) => {
// 响应结果里面有token 就把它保存起来
if(res.headers.authorization){
const token = res.headers.authorization.replace('Bearer','');
setToken(token);
ins.defaults.headers.Authorization = `Bearer ${token}`
}
// 响应结果里面有刷新token 也把它保存起来
if(res.headers.refreshtoken){
const refreshtoken = res.headers.refreshtoken.replace('Bearer','')
setRefreshToken(refreshtoken);
}
// 没有权限,刷新token
// 需要判断是否是refreshToken 如果刷新token也过期并且走这里,就会进入401死循环
if(res.data.code === 401 && !isRefreshRequest(res.config)){
// 刷新token
const isSuccess = await refreshToken()
// 判断刷新token是否成功
is(isSuccess){
// 保存新的token
res.config.headers.Authorization = `Bearer ${getToken()}`
// 有新的token后,重新请求
const resp = await ins.request(res.config)
return resp;
} else {
// 刷新失败,跳转到登录页
console.log(`跳转到登录页`)
}
}
return res.data;
})
export default ins;
2、index.js
import request from './request';
// 登录
export function login(){
return request.post('/login')
}
// 请求受保护的资源
export function reqProtected() {
return request.post('/protected')
}
export * from './refreshToken'
3.refreshToken.js
优化点:如果同时发出很多个请求,都失败了,都要重新去刷新token,就会导致refreshToken()在某一个时间点,并发执行很多次
import { getRefreshToken } from './token'
// 1、第一次刷新token的时候创建了一个promise
let promise;
export function refreshToken() {
// 2、有值就直接返回
if(promise){
return promise;
}
// 3、没有值就直接赋值
promise = new Promise(async (resolve,reject) => {
const resp = await request.get('/refresh_token',{
headers:{
Authorization:`Bearer ${getRefreshToken()}`
},
__isRefreshtoken:true
});
resolve(resp.code === 0);
})
promise.finally(()=>{
promise = null;
})
return promise;
}
// 把请求配置config传过去,看配置里面是否有这样一个属性 有的话就是一个刷新token的请求
export function isRefreshRequest(config){
return !!config.__isRefreshToken; // 两个取反把它变成布尔值
}