接口的偶尔捣乱让我事与愿违(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)
  }
)

最后成功按住躁动的它

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

相关推荐
小二·4 分钟前
Python Web 开发进阶实战:性能压测与调优 —— Locust + Prometheus + Grafana 构建高并发可观测系统
前端·python·prometheus
小沐°11 分钟前
vue-设置不同环境的打包和运行
前端·javascript·vue.js
qq_419854051 小时前
CSS动效
前端·javascript·css
烛阴1 小时前
3D字体TextGeometry
前端·webgl·three.js
桜吹雪1 小时前
markstream-vue实战踩坑笔记
前端
C_心欲无痕2 小时前
nginx - 实现域名跳转的几种方式
运维·前端·nginx
花哥码天下2 小时前
恢复网站console.log的脚本
前端·javascript·vue.js
LawrenceLan2 小时前
Flutter 零基础入门(十二):枚举(enum)与状态管理的第一步
开发语言·前端·flutter·dart
Zoey的笔记本2 小时前
「支持ISO27001的GTD协作平台」数据生命周期管理方案与加密通信协议
java·前端·数据库
C_心欲无痕3 小时前
Docker 本地部署 CSR 前端项目完整指南
前端·docker·容器