认识 AbortController控制器对象 及其应用

参考文章1
参考文章2

一、什么是AbortController (abort 意为 中止/废弃)

AbortController是一个控制器对象(DOM API),可通过new '构造函数'的方式生成控制器实例对象,可通过该控制器实例对象根据需要终止/取消一个或多个Web请求/监听事件

通过new生成的控制器实例对象很干净,身上只有一个abort()方法,和一个signal(AbortSignal对象)属性,signal属性上还有aborted、onabort、reason三个属性,我们主要使用aborted属性,表示是否已终止,其初始值为false

在这里插入图片描述

二、AbortController控制器怎么用

// 1.创建监听器实例对象
let controller = new AbortController();
// 2.获取signal对象
let signal = controller.signal;
// 3.给signal对象绑定监听事件
signal.addEventListener('abort',() => alert('abort!'),{ once: true });
// 4.在需要中止的任何时刻中止
controller.abort();

当控制器实例的方法abort()被调用时,实例的signal属性会触发abort事件,而abort事件的触发可以被监听,语法:signal.addEventListener('abort',()=>{},{once:true}),并将signal上的aborted属性变为true

与同一个signal关联的监听器只会触发一次abort事件,故在添加abort事件监听器之前,需确保该监听器的abort事件未触发过,检查signal.aborted属性是否为初始值false

任何绑定到signal的事件监听器都应使用{once:true},以确保在处理abort事件后立即删除事件监听器,否则可能导致内存泄漏

三、AbortController和fetch配合使用

AbortController可用于中止fetch请求

let controller = new AbortController();
// 将`AbortController`的`signal`对象属性作为fetch的第二个参数options上的可选属性进行传递
fetch(url,{
	signal:controller.signal
})

// `fetch`方法会监听属性`signal`上的`abort`事件,在想要中止fetch时调用controller.abort()即可
controller.abort();

当fetch请求被中止时,它的promise就进入reject回调,并返回名为AbortError的DOMException,因此需使用try/catch进行容错处理

let controller = new AbortController();
// 1s后中止fetch请求
setTimeout(()=>{
  controller.abort()
}, 1000);
// 容错处理
try{
	let response = fetch(url,{
		signal:controller.signal
	})
}catch(err){
	if(err.name === 'AbortError'){
		alert('Aborted!')
	}else{
		throw err;
	}
}

注意:已经abort的fetch请求是不能重复调用的,调用已经被abort的fetch请求,当读到signal的状态是aborted时,会直接进reject回调

fetch源码:

 // fetch源码仓库地址: https://github.com/github/fetch/blob/master/fetch.js 
  if (request.signal && request.signal.aborted) {
    return reject(new DOMException('Aborted', 'AbortError'))
  }

AbortController允许一次取消多个 fetch请求

let urls = [...]; // 要并行 fetch 的 url 列表
let controller = new AbortController();
// 一个 fetch promise 的数组
let fetchJobs = urls.map(url => fetch(url, {
  signal: controller.signal
}));

let results = await Promise.all(fetchJobs);
// controller.abort() 被从任何地方调用,它都将中止所有 fetch

如果我们有自己的与 fetch 不同的异步任务,我们可以使用单个 AbortController 中止这些任务以及 fetch。

在我们的任务中,我们只需要监听其 abort 事件:

let urls = [...];
let controller = new AbortController();
let ourJob = new Promise((resolve, reject) => { // 我们的任务
  ...
  controller.signal.addEventListener('abort', reject);
});

let fetchJobs = urls.map(url => fetch(url, { // fetches
  signal: controller.signal
}));

// 等待完成我们的任务和所有 fetch
let results = await Promise.all([...fetchJobs, ourJob]);

// controller.abort() 被从任何地方调用,
// 它都将中止所有 fetch 和 ourJob

四、AbortController和addEventListener配合使用

AbortController可作为addEventListener的第三个参数options上的可选属性
在这里插入图片描述
意思是,将controller的signal作为参数传进去,调用abort(),该监听器就会被移除

我们知道,取消监听器的方法removeEventListener(type, callback),这个callback必须和开启监听的callback是同一个函数引用,也就是说得把callback存下来,但有了signal就不用了

示例:实现按住鼠标后,监听鼠标的移动,松开鼠标后,取消监听

 const controller = new AbortController();
 function callback (e) {
   document.addEventListener('mousemove',  (e) => {
     // 回调处理函数
     // ...
   },
   { signal: controller.signal});
 }
 document.addEventListener('mousedown', callback);
 document.addEventListener('mouseup', controller.abort);
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值