axios拦截器重发请求,更新token
演示开发环境
编辑器:VsCode Vue:3.3.4 TypeScript:5.0.2 Element-Plus:2.3.7 Axios:1.4.0
依赖安装
Element-Plus:npm install element-plus --save
Axios:npm install axios --save
问题说明
ps:在我们开发的过程中,前端工程师 不可避免的一课就是处理 token(令牌),token有很多用途,常见的就是用于 用户认证鉴权、接口鉴权 等等,本文就拿这两个来展开叙述
axios 配置文件
1、新建一个 axiosConfig.ts
文件
2、在文件中配置 请求路径 、请求超时时间 ...等等,这里我只讲以下配置
ps:变量名称、函数名称可 自定义,为方便演示函数内容比较简单,具体可根据 实际情况 调整
// token本地存储关键词(相当于取本地token的钥匙)
tokenLocalKey: 'xxxx',
// token本地存储时间(单位:毫秒)
// 具体时间根据实际情况而定,这里设置为120分钟,
// 是因为我的后端接口返回的token有效期为120分钟
tokenLocalSaveTime: 120 * 60 * 1000,
// 保存token的函数
// 参数:存储key、token信息、存储时间
saveToken: (key: string, token: string, expire: number) => {
// 声明存储内容对象
const obj = {
token: token, // token信息
expire: Date.now() + expire // token有效时间
};
// 将内容存储到localStorage,内容格式为json字符串
localStorage.setItem(key, JSON.stringify(obj));
},
// 加载token的函数
// 参数:存储key
loadToken: (key: string) => {
// 获取本地存储的信息对象
const localInfo = localStorage.getItem(key);
if (localInfo) {
// 获取token信息,并返回
const { token } = JSON.parse(localInfo);
return token;
}
},
// 校验token是否过期
// 参数:存储key
checkToken: (key: string) => {
// 获取本地存储的信息对象
const localInfo = localStorage.getItem(key);
if (localInfo) {
// 获取token有效时间
const { expire } = JSON.parse(localInfo);
// 校验token是否过期,过期则移除token
if (Date.now() > expire) {
localStorage.removeItem(key);
}
}
}
axios 拦截器配置
ps:拦截器具体内容根据 实际需求 而定,不一定要使用我的逻辑
在封装 axios 请求的文件中引入以下依赖
// 引入 axios 库
import axios from 'axios';
// 引入 axios 配置文件,路径以实际项目为准
import axiosConfig from 'xxxx/axiosConfig';
// 引入 element-plus 的 ElMessage 组件
import { ElMessage } from 'element-plus';
// 引入 element-plus 的样式文件
import 'element-plus/dist/index.css';
请求拦截器 - request interceptors
// axios 请求拦截器
axios.interceptors.request.use(
(req) => {
// 控制台打印请求内容
console.log('请求拦截内容:{}', req);
// 执行token过期校验
axiosConfig.checkToken(axiosConfig.tokenLocalKey);
// 继续请求
return req;
},
(err) => {
// 控制台打印错误
console.log(err);
// 使用组件提示错误内容
ElMessage({
message: `请求时出错: ${err} !`,
type: 'error',
showClose: true,
center: true
});
}
);
响应拦截器 - response interceptors
// axios 响应拦截器
axios.interceptors.response.use(
async (resp) => {
// 控制台打印响应内容
console.log('响应拦截内容:{}', resp);
// 判断响应代码是否符合鉴权失败,这里的 1000 为后端接口返回鉴权失败的代码
if (resp.data.code && resp.data.code === 1000) {
// 获取请求的配置信息对象
let config = resp.config;
// 创建鉴权的 Promise 函数,这里因需求而异
// 我这里的token需要调用接口获取,所以需要用到异步函数
const authentication = new Promise((resolve) => {
// 调用封装的 axios 请求函数
ajax(
'/请求路径',
'请求参数',
(data: any) => { // 回调函数,返回请求的结果
// 执行保存的函数,这里我的后端返回的 data 就是 token
axiosConfig.saveToken(
axiosConfig.tokenLocalKey,
data,
axiosConfig.tokenLocalSaveTime
);
// 设置请求头内容(更新请求头的token信息)
config.headers.Authorization = data ? data : '';
// 处理返回结果
// 这里我的逻辑是不需要处理,直接执行 resolve 就行了
resolve(data);
},
'请求方法'
);
});
// 等待鉴权完成返回结果
await authentication;
// 重新发起请求
// 如果一直鉴权失败,并且token获取失败就会一直请求,
// 这里还有可优化空间,比如:设置重发请求失败错误限制次数、
// 重发等待时间等等,我就写的简单一点,你们自己升级优化啦
return axios(config);
}
return resp;
},
(err) => {
// 控制台打印错误
console.log(err);
// 使用组件提示错误内容
ElMessage({
message: `响应时出错: ${err} !`,
type: 'error',
showClose: true,
center: true
});
}
);
结语
希望对你能有所帮助,有问题可以私信或下方留言给我
转载自:https://juejin.cn/post/7282951856513400873