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

最后成功按住躁动的它

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

相关推荐
GIS程序媛—椰子9 分钟前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js
DogEgg_00115 分钟前
前端八股文(一)HTML 持续更新中。。。
前端·html
ZL不懂前端18 分钟前
Content Security Policy (CSP)
前端·javascript·面试
木舟100922 分钟前
ffmpeg重复回听音频流,时长叠加问题
前端
王大锤439132 分钟前
golang通用后台管理系统07(后台与若依前端对接)
开发语言·前端·golang
我血条子呢1 小时前
[Vue]防止路由重复跳转
前端·javascript·vue.js
黎金安1 小时前
前端第二次作业
前端·css·css3
啦啦右一1 小时前
前端 | MYTED单篇TED词汇学习功能优化
前端·学习
半开半落1 小时前
nuxt3安装pinia报错500[vite-node] [ERR_LOAD_URL]问题解决
前端·javascript·vue.js·nuxt