大家好,我是Kason。回想几年前的一次面试,面试官问我:promise的缺点是什么?想想真的好难……答案是:promise一旦初始化,就不能中止了。这是由承诺的执行情况决定的。AbortSignal的出现使得承诺在语义上是可中止的。此外,只要符合规范,所有异步操作都可以中止。什么是中止信号?AbortSignal是一个实验性的API,但是兼容性还不错,polyfill的实现也不复杂。AbortSignal可以实例化一个信号对象(signalobject)。AbortController可以为信号对象实例化一个控制器。就像遥控器可以发送信号来关闭电视一样,AbortController的实例可以控制中止信号。任何异步操作只要符合AbortSignal的接入规范,都可以实现abort功能。例如,首先新建一个控制器实例://controllerinstanceconstcontroller=newAbortController();常量信号=controller.signal;其中signal是控制器对应的信号对象。信号对象可以监听abort事件,该事件在信号中止时触发。信号在调用controller.abort()方法后会中止,此时signal.aborted为true。//监听中止事件signal.addEventListener('abort',()=>{console.log("Signalabort!")});//控制器中止信号controller.abort();console.log('中止:',signal.aborted);以上代码调用后,会依次打印:signalaborted!是否中止:truefetchAPI在fetch的应用中集成了AbortSignal。只需将控制器中的信号对象作为信号参数传递给fetch即可:constcontroller=newAbortController();提取(网址,{信号:控制器。信号});调用controller.abort()后,fetch的promise会变成RejectforAbortErrorDOMException:fetch('xxxx',{signal:controller.signal}).then(()=>{},err=>{if(err.name=='AbortError'){//abortsignal}else{//其他错误}})此时可以处理abort后的操作。这是一个取消视频下载的演示。可以看到fetch是如何配合AbortSignal来实现取消下载和任意异步操作的组合。信号参数被引入到合约中。如果API返回的promise变为AbortErrorDOMExceptionreject,则意味着操作被中止。如果signal.aborted===true,promise将立即更改为reject。观察AbortSignal状态的变化。如果API应用场景比较复杂(比如需要考虑多线程通信),文档提供了一套基于订阅和发布的abort-algorithms机制来完成第4步。总结虽然AbortSignal的原理是很简单,只要遵循访问规范,它的可扩展性很强。例如,你可以将一个信号传递给多个符合规范的API,你可以用一个控制器停止多个API的调用。就像一个遥控器,可以同时操作家里的空调、电视、洗衣机。你喜欢吗?欢迎加入人类优质前端框架研究组,带头
