接口的偶尔捣乱让我事与愿违(axios重复请求问题)

大家好,分享一下最近遇到的一个小问题:关于axios重复请求问题(新人第一篇)

背景:

最近遇到的项目中,遇到了四个selecte选项相互关联下拉数据对应更新的需求

按理说需求简单也应该不会出现什么问题,确实,在开发过程中也没遇到什么问题

但是在测试过程中发现一个bug

因为有一个接口要返回的数据量相比别的接口来说要大,返回时间相比来说很慢,无参数状态下该接口默认全返回,有参数反应的要快些。

复现场景:

当其中一个下拉框选中,另一个下拉数据会跟随对应变化

无选中就是参数为空的,调用的接口返回的是全数据,很慢

选中时候有参数,调用接口接口返回的数据很快

导致 选中-取消-选中 数据开始混乱, 拿到的可能是上一个接口返回的数据(慢返回的数据)

解决问题(AbortController):

注意:开始引入AbortController没有生效,我瞅了一眼版本是真的低,提升了下axios的版本
使用 Axios 您还可以使用 cancel token 取消一个请求,版本相对较低,但是不太推荐

那我们继续说

之前接口调用返回数据慢,可以取消请求,这个就用到了axios里面的AbortController

AbortController是一个控制器对象(DOM API),允许你对尚未完成的异步任务(如fetch请求)进行中止操作。

基本用法

  • 创建一个AbortController实例:

    js 复制代码
    	const controller = new AbortController();
  • 获取与该控制器关联的AbortSignal对象:

    js 复制代码
    	const signal = controller.signal;
  • 使用signal对象发起fetch请求,并将其作为fetch请求的第二个参数(options)的signal属性传递:

    js 复制代码
    	fetch('https://api.example.com/data', { signal })  
    	  .then(response => { /* 处理响应数据 */ })  
    	  .catch(error => {  
    	    if (error.name === 'AbortError') {  
    	      console.log('请求被中止');  
    	    } else {  
    	      console.error('请求失败', error);  
    	    }  
    	  });
  • 在需要取消请求时,调用AbortController实例的abort方法:

    js 复制代码
    	controller.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)
  }
)

最后成功按住躁动的它

感谢大家的浏览,也希望能够得到大家的肯定和指正

相关推荐
mCell44 分钟前
GSAP ScrollTrigger 详解
前端·javascript·动效
gnip44 分钟前
Node.js 子进程:child_process
前端·javascript
excel4 小时前
为什么在 Three.js 中平面能产生“起伏效果”?
前端
excel5 小时前
Node.js 断言与测试框架示例对比
前端
天蓝色的鱼鱼6 小时前
前端开发者的组件设计之痛:为什么我的组件总是难以维护?
前端·react.js
codingandsleeping6 小时前
使用orval自动拉取swagger文档并生成ts接口
前端·javascript
石金龙7 小时前
[译] Composition in CSS
前端·css
白水清风7 小时前
微前端学习记录(qiankun、wujie、micro-app)
前端·javascript·前端工程化
Ticnix8 小时前
函数封装实现Echarts多表渲染/叠加渲染
前端·echarts
用户22152044278008 小时前
new、原型和原型链浅析
前端·javascript