在有些场景下可能需要用到取消请求的操作,比如在同一时刻触发多次请求,只保留最新的请求;比如表单提交中关闭页面等行为,本文加少一些常用的触发 Web 请求的方式如何取消。
AbortControllor
AbortController
接口表示一个控制器对象,该对象允许您在需要时中止一个或多个 Web 请求。
AbortController
分别有一个属性 AbortController.signal
和一个方法 AbortController.abort
,他们结合起来可以用来终止 Web 请求。
它的使用过程如下:
首先创建一个 AbortController
对象 controller
,然后在调用 fetch
时,传入 controller.signal
作为选项,此时控制器和请求被关联在一起,使用控制器的 controller.abort
方法,即刻终止此请求。
const controller = new AbortController(); |
注意,当 controller.abort 被调用时, fetch 返回的 promise 会进入 reject 状态并返回一个名为 AbortError 的 DOMException。
AbortController.signal
搭配 AbortController.abort
还可以用来响应一些取消类的行为:
const controller = new AbortController(); |
注意,AbortControllor
只对浏览器原生的 fetch
生效,在日常开发中经常使用其它的工具如 axios
,下一节看一下 axios 怎么取消。
axios 请求取消
axios
提供了 cancelToken
配置项可以用来取消其请求,其使用和 AbortControllor
很相似,看下面的例子:
const cancelToken = axios.CancelToken; |
也可以给 CancelToken
传入一个执行器来执行:
const CancelToken = axios.CancelToken; |
都写到这里了,顺便看看 axios 内部是怎么实现取消的:
首先看 cancelToken 相关的代码:
// lib/adapters/xhr.js |
可以看到当 cancelToken.promise
调用 resolve
时进行了取消,结合它的使用不难猜测 cancelToken.source().cancel
和 传入 CancelToken
的 executor
返回给用户的方法一定用来是 resolve
cancelToken.promise
的,接着找相关代码:
// lib/cancel/CancelToken.js |
从上面看出 axios 的第一个示例 cancelToken.source
方法就是是调用了 CancelToken
构造器,也就是上面 axios 示例的第二种写法,后面就没必要看了,继续找构造器相关的代码就知道做了什么:
// lib/cancel/CancelToken.js |
很明显可以看出 this.promise
就是 config.cancelToken.promise.then
,而 executor
就是 new CancelToken
时传入的方法,最终暴露给外面了 function cancel
这个方法,而这个方法就是用来 config.cancelToken.promise
,和前面的猜测一致,不在多说。
同样的,使用同一个 cancelToken 也可以取消多个请求。
中止 Promise
Promise
也可以手动中止,只需要在创建 Promise
时,对外暴露 reject
:
let abort; |
XHR 请求取消
XHR 原生提供了 abort 方法,可以直接取消:
let xhr = new XMLHttpRequest(); |
注意,和其他不同的是,xhr 取消不会触发 error
事件,而是触发 abort
事件。