axios 请求拦截 取消重复请求(多次重复异步,结束 pending 状态)
前端开发中,会涉及很多异步事件处理,页面展示的处理关系最密切的就是 loading 图层,但是 loading 交互在一些时候会不太友好,后端同学也不喜欢 loading 状态(后端同学:这不就是说我的接口返回慢嘛?我的锅!)
前端函数节流防抖也是一个解决方法,但是又有一个问题是,我们处理的是异步,只要有异步就会有等待,比如,防抖时间是 1s,异步事件触发了两次,就需要最快 2s 完成,假设第一次异步 3s 返回,第二次异步 0.5 秒返回;那出现的情况就是,第一次触发的 3s 异步,1s 内没有返回,1s 后第二次触发异步,第一次的异步还没有返回,第二次的异步就就开始了,0.5 秒后第二次异步返回了,但是最终结果响应的是第一次的异步。
解决方案:利用 axios 可以很方便的取消重复请求的 pending 状态,结束重复请求,只让最后一次请求通过
官方文档:http://www.axios-js.com/zh-cn/docs/#%E5%8F%96%E6%B6%88
let pending = []; // 声明一个数组用于存储每个请求的取消函数和 axios 标识
let cancelToken = axios.CancelToken;
let removePending = (config) => {console.log('pending',pending);
for(let p in pending){if(pending[p].u === config.url.split('?')[0] + '&' + config.method) {
// 当当前请求在数组中存在时执行函数体
pending[p].f(); // 执行取消操作
pending.splice(p, 1); // 数组移除当前请求
}
}
}
// 请求拦截
service.interceptors.request.use(function(config) {
/*.....*/
removePending(config); // 在一个 axios 发送前执行一下取消操作
config.cancelToken = new cancelToken((c)=>{
// pending 存放每一次请求的标识,一般是 url + 参数名 + 请求方法,当然你可以自己定义
pending.push({u: config.url.split('?')[0] +'&' + config.method, f: c});//config.data 为请求参数
});
/*.....*/
})