更新:关于这个方案我重新再另一篇文章中更详细的讲了一遍有兴趣可以点这里:《依托 axios 实现全局请求防抖》
场景:当我们在发出请求后队列里有多个请求的时候,大幅度的消耗了后端的资源,进行了很多不必要的操作,比如:一个按钮重复的点击,接着前端发出请求(当然这种操作在点击事件中会做出判断,或者现有ui库已经做了loading操作这里只是打个比方)等。
解决方案:在请求拦截器中,查找当前请求队列里相同的域名接口,如果有,删除当前请求并返回上一个请求。这样,在同一队列里,只会出现同一个同域同名接口。
实例:
let pending = []; //声明一个数组用于存储每个ajax请求的取消函数和ajax标识
let removePending = config => {
for (let p in pending) {
if (
pending[p].u === config.url + "&" + config.method &&
!noCancelUrlList.includes(config.url.replace(baseURL, ""))
) {
//当当前请求在数组中存在时执行函数体
pending[p].f(); //执行取消操作
pending.splice(p, 1); //把这条记录从数组中移除
}
}
};
//添加请求拦截器
axios.interceptors.request.use(
config => {
removePending(config); //在一个ajax发送前执行一下取消操作
config.cancelToken = new cancelToken(c => {
// 这里的ajax标识我是用请求地址&请求方式拼接的字符串,当然你可以选择其他的一些方式
pending.push({ u: config.url + "&" + config.method, f: c });
});
return config;
},
error => {
return Promise.reject(error);
}
);
//添加响应拦截器
axios.interceptors.response.use(
response => {
if (response.data.code == 0 || response.data.type == 'FeatureCollection') { //请求成功或者为本地数据时返回,否则拦截
removePending(response.config);
//在一个ajax响应后再执行一下取消操作,把已经完成的请求从pending中移除
return response;
} else if (response.data && !response.data.code) {
//数据流获取过滤
removePending(response.config);
return response;
} else {
Message.error(response.data.errorMsg);
if (response.data.code == 1) {
window.location.href = "#/login";
}
}
},
error => {
return {
data: {
code: 666,
cancel: true,
errorMsg: "请求已关闭"
}
};
}
);