axios请求拦截和响应拦截的理解
01,02内容参考原文:https://blog.csdn.net/qq_59076775/article/details/124877699
结论:
01. 请求拦截
axios.interceptors.request.use((config)=>{
return config
},(error)=>{
return Promise.reject(error)
})
解析:请求拦截这个时候请求还没用发送出去,可以在config里面加一些东西,如在请求头里面携带token,此时还没有到达服务器,error关联的是请求错误返回的信息。举个例子,当你发送请求的时候,这个时候网络被中断,请求还没有到达服务器,但是报错了,这个使用会走error,通常也会进行返回一个Promise对象。
02. 响应拦截
axios.interceptors.response.use((config)=>{
return config
},(error)=>{
return Promise.reject(error)
})
解析:此时的请求已经到达了服务器,但是还没有到达客户端,可以对config进行一些操作,例如
进行一层结构的解析,返回return config.data,做一些统一错误处理,请求的时候只管成功,不管失败。error-------------它代表的是响应错误的返回值,如401,404,500的错误,权限不够,参数错误等一些列的错误:
if(status===401){
alert('权限不够')
}
else (status===404){
alert('参数错误')
}
else{
alert('其它错误')
}
token失效的处理
service.interceptors.response.use(
(response) => {
// dosomething
},
(error) => {
// ! 服务器响应失败时,干些事情: 导致响应失败的原因有很多,其中之一是 token 过期
// 响应失败时的error(错误对象),它经过了axios的2层包装,服务器响应的真实数据在 error.response.data 中。
// axios包装的提示信息是:error.message,与服务器响应的真实数据是两回事
const realData = error.response.data
/* 处理token失效---后端处理 */
if (error.response && realData && realData.code === 233333) {
// 以上三个条件全部满足时,才说明token超时
// 1. 触发actions中的logout函数,清除无效token、当前用户信息
store.dispatch('user/logout')
// 2. 跳转到登录页面
router.push({ path: '/login' })
// 3. return 一个执行错误,用于终止当前的promise执行链
return Promise.reject(error)
} else {
/* 如果token未失效,则是其他错误 */
// 1. 提示错误信息
Message.error(realData.message)
// 2. return 一个执行错误
return Promise.reject(error)
}
}
)
03. 我的应用
前期框架:
import axios, { InternalAxiosRequestConfig, AxiosResponse } from "axios";
// 创建axios实例
const service = axios.create({
// 请求的域名,基本地址,proxy 代理时会将“/api”以及前置字符串会被替换为真正域名: 相对路径: /dev-api 或者 绝对路径: http://localhost:8991 ; https://api.example.com
baseURL: import.meta.env.VITE_APP_BASE_API, // '/dev-api'
timeout: 50000,
headers: { "Content-Type": "application/json;charset=utf-8" },
});
//请求拦截器
service.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
console.log(config, "config--请求拦截器");
// 操作。。。
return config;
},
(error: any) => {
console.log(error, "error--请求拦截器");
return Promise.reject(error);
}
);
// 响应拦截器
service.interceptors.response.use(
(response: AxiosResponse) => {
console.log(response, "response--响应拦截器");
// 操作。。。。
// return response.data;
return response;
},
(error: any) => {
console.log(error, "error--响应拦截器");
// 操作。。。。
return Promise.reject(error.message);
}
);
// 导出axios实例
export default service;
优化:添加一些错误、权限等信息
需要跟后端开发协商好统一的字段,错误代码等信息。
import axios, { InternalAxiosRequestConfig, AxiosResponse } from "axios";
import { TOKEN_KEY } from "@/enums/CacheEnum";
import { ResultEnum } from "@/enums/ResultEnum";
import { ElMessage, ElMessageBox } from "element-plus";
import { useUserStoreHook } from "@/store/modules/user";
// 创建axios实例
const service = axios.create({
// 请求的域名,基本地址,proxy 代理时会将“/api”以及前置字符串会被替换为真正域名: 相对路径: /dev-api 或者 绝对路径: http://localhost:8991 ; https://api.example.com
baseURL: import.meta.env.VITE_APP_BASE_API,
timeout: 50000,
headers: { "Content-Type": "application/json;charset=utf-8" },
});
//请求拦截器
service.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
console.log(config, "config--请求拦截器");
// 操作。。。
const accessToken = localStorage.getItem(TOKEN_KEY);
if (accessToken) {
config.headers.Authorization = accessToken;
}
return config;
},
(error: any) => {
console.log(error, "error--请求拦截器");
return Promise.reject(error);
}
);
// 响应拦截器
service.interceptors.response.use(
(response: AxiosResponse) => {
console.log(response, "response--响应拦截器");
// 操作。。。
// 检查配置的响应类型是否为二进制类型('blob' 或 'arraybuffer'), 如果是,直接返回响应对象
if (
response.config.responseType === "blob" ||
response.config.responseType === "arraybuffer"
) {
return response;
}
const { code, data, msg } = response.data;
//成功: SUCCESS = "00000",
if (code === ResultEnum.SUCCESS) {
return data;
}
ElMessage.error(msg || "系统出错");
return Promise.reject(new Error(msg || "Error"));
},
(error: any) => {
console.log(error, "error--响应拦截器");
// 操作。。。。
// 异常处理
const { code, msg } = error.response.data;
// 令牌无效或过期: TOKEN_INVALID = "A0230",
if (code === ResultEnum.TOKEN_INVALID) {
ElMessageBox.confirm("", "", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
// 清除token 、重新加载。。。
const userStore = useUserStoreHook();
userStore.resetToken().then(() => {
location.reload();
});
});
} else {
ElMessage.error(msg || "系统出错");
}
return Promise.reject(error.message);
}
);
// 导出axios实例
export default service;