• antdpro使用AbortController取消请求


    官方api地址:https://developer.mozilla.org/zh-CN/docs/Web/API/AbortController
    umi-request案例:https://github.com/umijs/umi-request/blob/master/README_zh-CN.md#%E9%80%9A%E8%BF%87-abortcontroller-%E6%9D%A5%E4%B8%AD%E6%AD%A2%E8%AF%B7%E6%B1%82

    前言

    在某些场景下,如果频繁的操作导致第一次请求的数据在第二次请求之后返回,会出现数据被覆盖的情况

    基于 AbortController 方案来中止一个或多个DOM请求

    1、AbortController介绍

    AbortController是一个构造函数,可以创建控制器对象根据需要终止一个或者多个请求
    创建控制器对象

    let controller = new AbortController();

    1.1 实例的属性和方法

    1.1.1 signal

    将 signal 和对应的请求关联

    1.1.2 abort()

    用来终止同一实例的signal属性关联的请求

    2、案例

    2.1 api官网案例

    以 fetch请求为例

    var controller = new AbortController(); // 创建控制器实例
    var signal = controller.signal; 
    
    var downloadBtn = document.querySelector('.download');
    var abortBtn = document.querySelector('.abort');
    
    downloadBtn.addEventListener('click', fetchVideo);
    
    abortBtn.addEventListener('click', function() {
      controller.abort();  // 终止请求
      console.log('Download aborted');
    });
    
    function fetchVideo() {
      // …
      fetch(url, {signal}).then(function(response) {
        // …
      }).catch(function(e) {
        reports.textContent = `Download error: ${e.message}`;
      })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    2.2 umi-request案例

    // 按需决定是否使用 polyfill
    import 'yet-another-abortcontroller-polyfill'
    import Request from 'umi-request';
    
    const controller = new AbortController(); // 创建一个控制器
    const { signal } = controller; // 返回一个 AbortSignal 对象实例,它可以用来 with/abort 一个 DOM 请求。
    
    signal.addEventListener('abort', () => {
      console.log('aborted!');
    });
    
    Request('/api/response_after_1_sec', {
      signal, // 这将信号和控制器与获取请求相关联然后允许我们通过调用 AbortController.abort() 中止请求
    });
    
    // 取消请求
    setTimeout(() => {
      controller.abort(); // 中止一个尚未完成的DOM请求。这能够中止 fetch 请求,任何响应Body的消费者和流。
    }, 100);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2.3 antdpro项目案例

    action.js
    // 全局状态,并返回通信方法
    import { initGlobalState } from 'qiankun';
    import 'yet-another-abortcontroller-polyfill'; 
    import _ from 'lodash';
    
    let state = {};
    const actions = initGlobalState(state);
    actions.setState = (info) => {
      state = { ..._.cloneDeep(state), ...info };
      actions.setGlobalState(state);
    };
    
    actions.createController = (url) => {
      // 创建Controller 控制器
      state = { ..._.cloneDeep(state), [url]: new AbortController() };
      actions.setGlobalState(state);
    };
    
    actions.getState = (key) => {
      return key ? state[key] : state;
    };
    export { actions };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    utils/request.js
    import axios from './axios'
    import { actions } from '@/actions'; // ‘qiankun’ 封装的全局状态
    const request = async (url, options) => {
    	const controller = actions.getState(url)
      // 如果存在证明当前url的请求之前已经发送
      if (controller) {
        controller.abort(); // 终止上一次的请求
        actions.createController(url); //自定的方法 初始化关联新的控制器
      }
    }
    
    export default request
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    utils/axios.js
    // antdpro中的request文件,用来补充请求拦截,自定义异常,统一异常处理等
    
    // ...		其他引入的依赖
    import 'yet-another-abortcontroller-polyfill';
    import { extend } from 'umi-request';
    import { actions } from '@/actions'; // ‘qiankun’ 封装的全局状态
    
    const request = extend({
      errorHandler, // 默认错误处理
      timeout: 100000, // 超时时间
    });
    
    let controller = null;
    
    // 请求拦截
    request.interceptors.request.use(async (url, options) => {
      const allActions = actions.getState();
      controller = allActions[url];
      if (!controller) {
        const allActions = actions.getState();
        controller = new AbortController(); // 创建一个控制器
        actions.setState({ ...allActions, [url]: controller });
      }
      // ... 其他逻辑
    
      return {
        url: url,
        options: {
          ...options,
          ...(controller?.signal && { signal: controller.signal }),
          headers: headers,
        },
      };
    });
    
    // ... 其他逻辑
    
    export default request;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    使用的时候引入utils/request 传url和参数就行

  • 相关阅读:
    [含毕业设计论文+PPT+源码等]ssm装潢应用系统小程序+Java后台管理系统|前后分离VUE
    【云原生之k8s】kubernetes原理
    概率统计·大数定律及中心极限定理【大数定律、中心极限定律】
    中国石油大学(北京)-《 油层物理》第一阶段在线作业
    linux入门---多线程的控制
    【计网】二、物理层
    Xcode 15 编译出错问题解决
    Spring实现Bean注入的常见方式
    react,hooks中的useRef使用
    指针进阶(3)
  • 原文地址:https://blog.csdn.net/qq_41534913/article/details/127774754