import axios from "axios";
import qs from "qs";
//创建axios的一个实例
var instance = axios.create({
baseURL: import.meta.env.VITE_BASE_API_URL, //接口统一域名
timeout: 30000, //设置超时
});
//创建存储 key 的 集合
let keyMap = new Map();
//获取每一次请求的key
function getRequestKey(config) {
let { url, method, data, params } = config;
//记得这里一定要处理 每次请求都掉会变化的参数(比如每个请求都携带了时间戳),否则二个请求的key不一样
let key = [url, method, qs.stringify(data), qs.stringify(params)].join("&");
return key;
}
//判断是否存在该key,不存在则插入
function checkRequest(config, source) {
let key = getRequestKey(config);
if (keyMap.has(key)) {
source.cancel();
} else {
keyMap.set(key, config);
}
}
//响应完成后,删除key
function deleteRequestKey(config) {
let key = getRequestKey(config);
if (keyMap.has(key)) {
keyMap.delete(key);
}
}
//请求拦截器
instance.interceptors.request.use(config => {
//这里 是拦截的关键,使用 axios CancelToken, 每次请求都重新生成 source 和 cancelToken
const source = axios.CancelToken.source();
config.cancelToken = source.token;
//检查请求
checkRequest(config, source);
return config;
});
//响应拦截器
instance.interceptors.response.use(
result => {
// 这里是占位, 第二个是错误处理函数
return result;
},
error => {
//拦截掉重复请求的错误,中断promise执行
if (axios.isCancel(error)) {
return new Promise(() => {});
}
//不是重复请求错误放行 到 .catch 中
return Promise.reject(error.response);
}
);
//封装请求
let request = function (config) {
//如果你是这里用if处理 config.method 的情况,那么你要注意
//这里不会像拦截器那样将 config.method 转换成小写, 你需要自己处理
//config.method = config.method.toLowerCase();
return new Promise(function (resolve, reject) {
instance(config)
.then(res => {
// 请求成功了但返回没有 data 内容放行到 外层的Promise 的 .catch
if (res && res.data != "") {
resolve(res.data);
} else {
reject(res);
}
})
.catch(err => {
reject(err);
})
.finally(_ => {
// 删除已完成的请求 key
deleteRequestKey(config);
});
});
};
export default request;
代码可以直接使用, 如果要封装
get post
可以以request
为标准,重新封装,request
并没有做过多处理, 根据自己需求 添加即可, 大致意思已经打上了注释
觉得有用就点个赞吧