封装新版axios(v0.22.0)中的取消请求

4,429 阅读3分钟

我正在参加「掘金·启航计划」

Hi~,我是一碗周,一个在舒适区垂死挣扎的前端,如果写的文章有幸可以得到你的青睐,万分有幸~~

之前有一篇封装axios的文章火了,在写这篇文章的时候已经接近10W的阅读量了,就是这篇:在项目中用ts封装axios,一次封装整个团队受益😁 - 掘金 (juejin.cn)

image.png

文章中的代码思路是借鉴王红元(coderwhy)老师的思路,发这篇文章的时候没有想过有这么高的阅读量,这就导致有人说封装没有意义、过渡封装、等等吧,其实我想说这就是一篇记录学习过程和分享封装思路的文章,没有必要这么较真吧~

有一个好兄弟专门写了一篇文章来回复过渡封装axios,这里也谢谢你拿我的文章举反面例子,让我明白有哪些不足。那篇文章我也认真拜读了,确实受益匪浅,谢谢指正~

说了这么多废话,正文开始~

🍇 写在前面

axiosv0.22.0之前取消请求是使用的cancel token API,而在v0.22.0开始使用的是AbortController,我写封装axios时还是使用的cancel token API,这里更新一下,相对来说后者取消请求的方式更为简单,这里简单举个例子。

✈️ 简单介绍一下AbortController

这里先简单介绍一下AbortController,其实也比较简单,我们可以通过new来实例化一个控制器对象,然后将该控制器对象与请求进行‘绑定’,然后调用对象的abort()来取消一个或者多个请求。在axios中也有明确的示例:

const controller = new AbortController();

axios.get('/foo/bar', {
  // 将控制器与请求进行‘绑定’
  signal: controller.signal
}).then(function(response) {
   //...
});
// 取消请求
controller.abort()

相对来说代码已经非常的少了。

在兼容性方面除了IE都支持

image.png

如果想要考虑兼容IE的小伙伴就要放弃该方案了。

🌻 主要思路

这里先说一下我的主要思路:

  1. 创建一个Map用于存储控制器对象;
  2. 在请求拦截器中将控制器存入Map;
  3. 在响应拦截器中将控制器从Map中移除;
  4. 封装一个取消全部请求的方法;
  5. 封住一个可以取消指定请求的方法;

OK,思路说完了,我们来正式进入代码。

首先定义一个存储控制器对象的Map:

// * 存放取消请求控制器Map
abortControllerMap: Map<string, AbortController>

然后在请求拦截器中存入Map:

// * 请求拦截器中加入下面这段代码片段
const controller = new AbortController()
const url = res.url || ''
res.signal = controller.signal
this.abortControllerMap.set(url, controller)

我们不能只存入不删除,所以需要在响应拦截器中加入从Map中移除的代码:

const url = res.config.url || ''
this.abortControllerMap.delete(url)

现在我们来封装一下取消全部请求的方法,取消全部请求比较简单,只需要迭代Map并调用abort()方法即可,代码如下:

/**
 * 取消全部请求
 */
cancelAllRequest() {
  for (const [, controller] of this.abortControllerMap) {
    controller.abort()
  }
  this.abortControllerMap.clear()
}

最后我们来封装一下取消指定请求的方法,因为我们的Map使用的是RUL做key,所以取消请求也是需要使用URL作为参数,代码如下:

/**
 * 取消指定的请求
 * @param url 待取消的请求URL
 */
cancelRequest(url: string | string[]) {
  const urlList = Array.isArray(url) ? url : [url]
  for (const _url of urlList) {
    this.abortControllerMap.get(_url)?.abort()
    this.abortControllerMap.delete(_url)
  }
}

🐬 写在最后

OK了,就这么点内容,相对cancel token API来说代码量会少一部分。

对了,完整代码在ywanzhou/vue3-template (github.com)中。