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

最后成功按住躁动的它

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

相关推荐
abc80021170348 分钟前
前端Bug 修复手册
前端·bug
Best_Liu~11 分钟前
el-table实现固定列,及解决固定列导致部分滚动条无法拖动的问题
前端·javascript·vue.js
_斯洛伐克1 小时前
下降npm版本
前端·vue.js
苏十八2 小时前
前端进阶:Vue.js
前端·javascript·vue.js·前端框架·npm·node.js·ecmascript
st紫月3 小时前
用MySQL+node+vue做一个学生信息管理系统(四):制作增加、删除、修改的组件和对应的路由
前端·vue.js·mysql
乐容3 小时前
vue3使用pinia中的actions,需要调用接口的话
前端·javascript·vue.js
似水明俊德4 小时前
ASP.NET Core Blazor 5:Blazor表单和数据
java·前端·javascript·html·asp.net
至天5 小时前
UniApp 中 Web/H5 正确使用反向代理解决跨域问题
前端·uni-app·vue3·vue2·vite·反向代理
与墨学长5 小时前
Rust破界:前端革新与Vite重构的深度透视(中)
开发语言·前端·rust·前端框架·wasm
H-J-L5 小时前
Web基础与HTTP协议
前端·http·php