介绍
AbortController 是用来适配 AbortSignal
接口的对象,封装了关于终止的行为(AbortController.abort())。
一般而言,都会使用 AbortController 新建一个控制器,随后通过 abortController.signal
获取 AbortSignal
的具体实现,在需要的地方通过 AbortController.abort()
终止目标行为,比较常见的场合可以使用在 fetch (终止 fetch)或是 stream(获取 stream 终止行为) 上。
注意事项
当你需要编写一些 node 和 浏览器都需要使用的 API 时,使用
AbortController
是一个不错的选择,但是AbortController
是一个在v15.0.0
以及v14.17.0
才加入的特性,如果你需要面向相对较旧的 node 版本编写 api 时,他可能并不是最好的选择。
在 fetch 上使用
比较常见的场景是在 fetch 上,你可以通过他简单的实现一个取消操作:
这样就能简单的在用户点击取消的时候,正确的终止 fetch 行为。
超时
而基于此方案同样可以更简单的实现超时行为的控制, 但是由于 timeout 方法实现在 AbortSignal 上,所以事实上 无法方便 的组合 自定义取消 和 超时。
组合 AbortSignal
警告: AbortSignal 无法同时支持超时和自定义取消
假设你需要 超时 支持超时和自定义取消,你必须 自行实现 类似于如下代码:
或是通过 AbortSignal
提供的组合方法 AbortSignal.any
:
AbortSignal.any
姑且算是好用,可惜是 2024年 5 月才推广到所有浏览器可用,最起码也要 chrome 116 版本以上,不是一个完全可用的 API
stream
一般来说在 stream 中 AbortController 只是用来获取 abort
事件的,相当于官方提供了统一的 abort 接口,而类似于以前写的 createWritable
这样的 API 都没有提供直接的方法以供使用。
通常得使用更为手动的 API 比如 WritableStream
:
以上
controller
也同样在ReadableStream
中有所实现
错误事件
在 AbortSignal 事件监听返回值为 AbortSignal 对象,通常可以使用下面的方式获取
上文中的代码就是常见的将 AbortController 同 promise
混合使用,随后利用 event.target
获取 reason
。
reason 返回的是一个 AbortError
对象,你可以很方便的使用 reason.name === 'AbortError'
来判断。
注意
请注意在浏览器中 AbortSignal 的错误继承自
DOMException
, 不存在AbortError
类型
其他应用场景
在 axios 上的使用
在我们项目里面最早使用 axios 的版本是 0.21.1
由于那个时候使用的比较早,所以无法通过 AbortController
来实现,所以实现上是类似于下面这种方式:
而现在(大于 0.22.0
版本)可以直接通过 AbortController
实现了:
在 vueuse 中使用
vueuse 的部分 api 也提供了 abort controller 的适配,譬如:
useAsyncQueue
useEyeDropper
useFetch
使用方法就是在 option 中传递 signal 字段即可。
总结
AbortController
和 AbortSignal
提供了浏览器、nodejs 中官方的关于取消行为的 api 接口,更好的约束了 abort
这一行为的实现,如果你的 API 需要实现 abort
的行为,那么对齐标准是个不错的选择。
本文标题:试试用 AbortController 来替代自己实现的取消 API
永久链接:https://iceprosurface.com/code/front-end/abort-controller/
作者授权:本文由 icepro 原创编译并授权刊载发布。
版权声明:本文使用「署名-非商业性使用-相同方式共享 4.0 国际」创作共享协议,转载或使用请遵守署名协议。