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}`;
  })
}

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);

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 };

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

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;

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

你可能感兴趣的:(qiankun微前端实战,前端,AbortController,antdpro,react)