大家好,分享一下最近遇到的一个小问题:关于axios重复请求问题(新人第一篇)
背景:
最近遇到的项目中,遇到了四个selecte选项相互关联下拉数据对应更新的需求
按理说需求简单也应该不会出现什么问题,确实,在开发过程中也没遇到什么问题
但是在测试过程中发现一个bug
因为有一个接口要返回的数据量相比别的接口来说要大,返回时间相比来说很慢,无参数状态下该接口默认全返回,有参数反应的要快些。
复现场景:
当其中一个下拉框选中,另一个下拉数据会跟随对应变化
无选中就是参数为空的,调用的接口返回的是全数据,很慢
选中时候有参数,调用接口接口返回的数据很快
导致 选中-取消-选中 数据开始混乱, 拿到的可能是上一个接口返回的数据(慢返回的数据)
解决问题(AbortController):
注意:开始引入AbortController没有生效,我瞅了一眼版本是真的低,提升了下axios的版本
使用 Axios 您还可以使用 cancel token 取消一个请求,版本相对较低,但是不太推荐
那我们继续说
之前接口调用返回数据慢,可以取消请求,这个就用到了axios里面的AbortController
AbortController是一个控制器对象(DOM API),允许你对尚未完成的异步任务(如fetch请求)进行中止操作。
基本用法:
-
创建一个
AbortController
实例:jsconst controller = new AbortController();
-
获取与该控制器关联的
AbortSignal
对象:jsconst signal = controller.signal;
-
使用
signal
对象发起fetch请求,并将其作为fetch请求的第二个参数(options)的signal
属性传递:jsfetch('https://api.example.com/data', { signal }) .then(response => { /* 处理响应数据 */ }) .catch(error => { if (error.name === 'AbortError') { console.log('请求被中止'); } else { console.error('请求失败', error); } });
-
在需要取消请求时,调用
AbortController
实例的abort
方法:jscontroller.abort();
代码实现:
外部定义
js
//正在请求 还没返回的请求
const requestList = new Map();
//请求名单: 为特殊接口添加防重复请求,有些接口不需要这个定义,可能也是我接手项目的原因,老版代码
const whiteRequestList = [
'v1/manager/2b/operation3/list&get',
'v1/manager/2b/operation4/list&get',
];
const service = axios.create({
baseURL: process.env.BASE_URL, // url = base url + request url
timeout: 5000 // request timeout
})
请求拦截器
js
service.interceptors.request.use(
config => {
const { url, method } = config;
//map中key值
let parameter = url + '&' + method;
//判断缓存map请求里面是否存在当前key值
let oldControl = requestList.get(parameter);
//缓存中存在请求key 以及当前key在防重复请求名单里面
if(!!oldControl && whiteRequestList.includes(parameter)) {
// 取消请求
oldControl.abort();
//删除缓存管理请求
requestList.delete(parameter)
}
//创建请求管理器
const control = new AbortController();
//为每个请求配置添加signal属性
config.signal = control.signal;
//将每一次的control进行缓存
requestList.set(parameter,control);
return config
},
error => {
return Promise.reject(error)
}
)
响应拦截器
js
service.interceptors.response.use(
response => {
const res = response.data;
//响应成功删除缓存地址
const { url, baseURL, method } = response.config;
let parameter = url.replace(baseURL+'/','') + '&' + method;
requestList.delete(parameter);
if (res.code !== 200) {
Message({
message: res.message || 'Error',
type: 'error',
duration: 2 * 1000
})
return Promise.reject(new Error(res.message || 'Error'))
} else {
return res
}
},
error => {
return Promise.reject(error)
}
)
最后成功按住躁动的它
感谢大家的浏览,也希望能够得到大家的肯定和指正