官方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请求
AbortController是一个构造函数,可以创建控制器对象根据需要终止一个或者多个请求
创建控制器对象
let controller = new AbortController();
将 signal 和对应的请求关联
用来终止同一实例的signal属性关联的请求
以 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}`;
})
}
// 按需决定是否使用 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);
// 全局状态,并返回通信方法
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 };
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
// 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和参数就行