大家好,我卡颂。
遐想数年前的一次面试,面试官问我:promise
有什么毛病?
真是百思不得姐啊...
答案是:promise
一旦初始化,就不能停止。这是由promise
的实现决定的。
AbortSignal
的呈现使promise
从语义上变为可停止的。并且,只有符合规范,所有异步操作都能变为可停止的。
AbortSignal是什么
AbortSignal
是个实验性API
,不过兼容性还不错,而且polyfill
实现起来也不简单。
AbortSignal
能够实例化一个信号对象(signal object
)。
AbortController
能够实例化一个信号对象的控制器。
就像遥控器能够发出信号关电视一样,AbortController
的实例能够管制停止信号。
只有合乎AbortSignal
的接入标准,任何异步操作都能实现停止性能。
举个例子,首先new
一个控制器实例:
// 控制器实例const controller = new AbortController();const signal = controller.signal;
其中signal
是控制器对应的信号对象。
信号对象能够监听abort
事件,当信号被停止时被触发。
调用controller.abort()
办法后会停止信号,此时signal.aborted
为true
。
// 监听 abort 事件signal.addEventListener('abort', () => { console.log("信号停止!")});// 控制器停止信号controller.abort(); console.log('是否停止:', signal.aborted);
如上代码调用后会顺次打印:
- 信号停止!
- 是否停止:true
在fetch中的利用
fetch API
曾经集成了AbortSignal
。
只须要将controller
内的信号对象作为signal
参数传给fetch
:
const controller = new AbortController();fetch(url, { signal: controller.signal});
当调用controller.abort()
后,fetch
的promise
会变为AbortError DOMException reject
:
fetch('xxxx', { signal: controller.signal}).then(() => {}, err => { if (err.name == 'AbortError') { // 停止信号 } else { // 其余谬误 }})
能够在此时解决停止后的操作。
这里有个勾销视频下载Demo,能够看看fetch
如何配合AbortSignal
实现勾销下载
与任何异步操作联合
不仅是fetch
,任何异步操作只有合乎如下标准,都能够与AbortError
集成:
- 将
AbortSignal
(信号对象)作为API
的signal
参数传入 - 约定如果
API
返回的promise
变为AbortError DOMException reject
则代表操作被停止 - 如果
signal.aborted === true
则立即让promise
变为reject
- 观测
AbortSignal
状态的变动
如果API
利用场景比较复杂(比方须要思考多线程通信),文档中提供了一套基于订阅公布的abort-algorithms机制来实现步骤4。
总结
尽管AbortSignal
原理很简略,但只有恪守接入标准,他的可扩展性是很强的。
比方,能够将一个signal
传给多个符合规范的API
,就能用一个控制器停止多个API
的调用。
就像一个遥控器,同时操作家里的空调、电视、洗衣机,你爱了么?
欢送退出人类高质量前端框架钻研群,带飞