AbortSignal:以前我没得选,现在我想中止Promise

开发 前端
AbortSignal的出现使promise从语义上变为可中止的。并且,只要符合规范,所有异步操作都能变为「可中止的」。AbortSignal是个实验性API,不过兼容性还不错,而且polyfill实现起来也不复杂。

[[426765]]

大家好,我卡颂。

遥想数年前的一次面试,面试官问我:promise有什么缺点?

真是百思不得姐啊...

答案是:promise一旦初始化,就不能中止。这是由promise的实现决定的。

AbortSignal的出现使promise从语义上变为可中止的。并且,只要符合规范,所有异步操作都能变为「可中止的」。

AbortSignal是什么

AbortSignal是个实验性API,不过兼容性还不错,而且polyfill实现起来也不复杂。

AbortSignal可以实例化一个「信号对象」(signal object)。

AbortController可以实例化一个「信号对象」的控制器。

就像遥控器可以发出信号关电视一样,AbortController的实例可以控制中止信号。

[[426766]]

只要符合AbortSignal的接入规范,任何异步操作都能实现中止功能。

举个例子,首先new一个控制器实例:

  1. // 控制器实例 
  2. const controller = new AbortController(); 
  3. const signal = controller.signal; 

其中signal是控制器对应的「信号对象」。

「信号对象」可以监听abort事件,当信号被中止时被触发。

调用controller.abort()方法后会中止信号,此时signal.aborted为true。

  1. // 监听 abort 事件 
  2. signal.addEventListener('abort', () => { 
  3.   console.log("信号中止!"
  4. }); 
  5.  
  6. // 控制器中止信号 
  7. controller.abort();  
  8.  
  9. console.log('是否中止:', signal.aborted);  

如上代码调用后会依次打印:

  1. 信号中止!
  2. 是否中止:true

在fetch中的应用

fetch API已经集成了AbortSignal。

只需要将controller内的「信号对象」作为signal参数传给fetch:

  1. const controller = new AbortController(); 
  2. fetch(url, { 
  3.   signal: controller.signal 
  4. }); 

当调用controller.abort()后,fetch的promise会变为AbortError DOMException reject:

  1. fetch('xxxx', { 
  2.   signal: controller.signal 
  3. }).then(() => {}, err => { 
  4.   if (err.name == 'AbortError') {  
  5.     // 中止信号 
  6.   } else { 
  7.     // 其他错误 
  8.   } 
  9. }) 

可以在此时处理中止后的操作。

这里有个取消视频下载Demo[1],可以看看fetch如何配合AbortSignal实现取消下载

与任何异步操作结合

不仅是fetch,任何异步操作只要符合如下规范,都可以与AbortError集成:

  1. 将AbortSignal(信号对象)作为API的signal参数传入
  2. 约定如果API返回的promise变为AbortError DOMException reject则代表操作被中止
  3. 如果signal.aborted === true则立刻让promise变为reject
  4. 观测AbortSignal状态的变化

如果API应用场景比较复杂(比如需要考虑多线程通信),文档中提供了一套基于「订阅发布」的abort-algorithms[2]机制来完成步骤4。

总结

虽然AbortSignal原理很简单,但只要遵守接入规范,他的可扩展性是很强的。

比如,可以将一个signal传给多个符合规范的API,就能用一个控制器中止多个API的调用。

就像一个遥控器,同时操作家里的空调、电视、洗衣机,你爱了么?

参考资料

[1]取消视频下载Demo:

https://mdn.github.io/dom-examples/abort-api/[2]abort-algorithms:

https://dom.spec.whatwg.org/#abortsignal-abort-algorithms

 

责任编辑:姜华 来源: 魔术师卡颂
相关推荐

2022-06-08 13:48:06

物联网卡智能设备SIM卡

2021-03-09 07:37:42

技术Promise测试

2013-10-09 09:39:17

开源

2021-03-22 08:58:23

程序员产品经理

2018-04-05 22:42:43

2021-09-06 06:45:06

普通索引唯一

2022-07-05 16:36:19

通信网络通信故障

2022-01-04 20:52:50

函数异步Promise

2010-12-10 09:11:00

Oracle服务器操作系统

2021-04-16 07:53:03

Zookeeper分布式系统

2024-01-25 18:00:56

微服务系统KafkaRabbitMQ

2018-02-25 11:00:34

代码开发程序员

2015-07-27 14:54:57

2020-09-15 12:59:48

KotlinFlutter移动

2018-07-16 16:39:00

数据

2013-06-17 11:21:27

2020-02-18 13:55:57

Python 开发编程语言

2015-02-11 10:37:58

腾讯ROM

2020-12-15 15:21:41

C++JavaPython

2020-04-14 16:35:31

戴尔
点赞
收藏

51CTO技术栈公众号