AbortController 中止 Promise

926 阅读4分钟

前言

  俺是梅十三,一只躺平的猫,觉得有意思就分享点东西

promise

  这玩意的基本用法大家都知道,我就不再赘述,他有一个特点,一旦初始化,就不能中止。

  不过,他有个状态叫pennding,意思就是你不返回resolve也不返回reject,他就会一直这么挂着不走下去,等你把他要的给了,他才愿意往下走,你要说这有啥用?我们看个例子

  代码很简单,点击开始按钮啥也不干5秒后显示接受,如果中间你点了一下中止按钮,那就显示躺平,在到5s之前,在你中止他之前,他就一直是pennding,他的resolve状态由自己内部控制,而他的reject状态被我们拿了出来由我们控制,这样就很简单的实现了一个promise的中止效果。

上面代码块的codeSendBox,觉得有意思想运行看看的,可以点进去

AbortController

  有人可能奇怪既然可以自己实现外部控制promise的状态,为什么还需要专门的api呢,再用这个AbortController不是多此一举么?

  答案是当然不是,我们都知道现在主流的网络请求是axiosfetch,一个是基于xhr封装的,用的xhr的api实现中止请求功能,一个是浏览器原生支持的,但是没有原生的中止请求api,fetch就是用abortController实现的中止请求功能。这就直接证明了这个api的价值。但是在介绍AbortController之前我们先回顾一下上面的例子,中止promise其实是有一点响应式的感觉,promise会立即响应状态的变更,但我们改变状态的方法不是响应式的,而是一个取巧的方法,把reject函数返回给了一个中间变量,并且把这个中间变量存储在专用的容器里,然后我们再通过这个容器去执行中间变量对应的rejectreject的内容由外部决定,这其实很不合理,因为具体reject什么不应该是外部要关注的,这会让这个promise变得难以理解,且维护也更加苦难,毕竟还有一个容器要一起维护。

AbortController则解决了我们上述的问题,它改变状态的方法也是响应式的,我们不需要劫持reject或者resolve,也不需要容器。

现在我们来介绍一下这个api,这个东西是一个控制器对象,但我觉得这么说不形象,说它是一套遥控炸弹设备比较形象,一套两件,一件炸弹,一件遥控器,

const controllerSuit = new AbortController(); // 实例化遥控炸弹套件
const signal = controllerSuit.signal // 拿出炸弹
const controller = controllerSuit.abort // 拿出遥控器

我们可以看到,就两个属性,非常简单,接下来看一下使用的实例

下面代码块的codeSendBox,觉得有意思想运行看看的,可以点进去

  这是模拟了一个fetch请求中止的实现,也就是用abortController实现的中止promise,总体思路也很简单,专门封一个受控promise里面塞上炸弹signal,然后和请求的request一起塞到race里,你要是想终止了,就按一下桶里的遥控器,然后挂在signal上的事件立马就会执行,炸弹爆炸,请求中止。

  你可能会好奇了,这个signal炸弹为什么可以注册事件在上面?因为这东西它继承了EventTarget,是一个dom接口,可以接受事件,创建侦听器,这也是他为什么可以响应式的执行,炸弹么,不响应那就是残次品了

image.png

  我们可以看到这个signal是麻雀虽小,但五脏俱全,你按下遥控器,它内部的aborted就会变为true,然后就会执行你绑定的事件,是不是很好理解,哈哈。

结语

  第一次发文章,工作时间也不长,肯定有很多写的不好的地方,希望大家多多批判,不要留情。