axios全局封装AbortController取消重复哀求

打印 上一主题 下一主题

主题 797|帖子 797|积分 2391

为什么?

题目:为什么axios要配置AbortController?防抖节省不行吗?
分析:


  • 防抖节省本质上是用延时器来操作哀求的。
  • 防抖是判断延时器是否存在,假如存在,扫除延时器,重新开启一个延时器,只执行最后一次哀求。
  • 节省呢,是判断延时器是否存在,假如存在,直接return掉,直到执行完这个延时器。
  • 事实上,这些体验感都不算友好,由于对于用户来说,得等一些时间,尤其是首次哀求,不是那么流畅。
  • 而当我们配置了AbortController,就可以停止掉重复的哀求,而且首次不需要等待时间,好坏常友好的举动。
  • 从axios0.22.0开始,开始支持AbortController,而且废弃CancelToken。之以是我们不用CancelToken来取消哀求,是由于CancelToken存在内存走漏隐患,并不安全,以是官方人员盼望用户们升级版本,利用AbortController镌汰内存走漏风险。
  • 事实上,凡事用xhr封装的哀求库,都可以配置AbortController,如fetch,axios,alova等等
  • 本文封装的原理可以移步至另一篇博客检察:如何避免接口重复哀求(axios保举利用AbortController)-CSDN博客
前置条件:

升级axios至最新版本。由于AbortController是从0.22.0开始支持的。假如你的版本已经在0.22.0以上,可以正常利用,不升级亦可。
以笔者升级的项目为例,我这里的版本是很古老的0.18.0,以是我这里是直接把axios升级至现在最新的稳定版本1.7.2。(假如升级失败,可以先移除掉axios,再重新安装。)
  1. //安装axios
  2. npm i axios
  3. //卸载axios
  4. npm uninstall axios
复制代码
接入步骤:

1.在封装axios的全局文件中,先定义两个变量

  1. 在全局封装axios的request.js文件的全局里定义两个变量
  2. isCancel 用来判断请求是否被取消
  3. cacheRequest 用来存储需要取消重复请求的接口
复制代码
  1. // isCancel-取消标识 可以根据这个值判断请求是否被取消
  2. const { isCancel } = axios
  3. const cacheRequest = {}
复制代码
2.定义一个函数,用来取消哀求和删除cacheRequest里对应的哀求

  1. // 删除缓存队列中的请求
  2. function abortCacheRequest(reqKey) {
  3.   if (cacheRequest[reqKey]) {
  4.     // 通过AbortController实例上的abort来终止请求
  5.     cacheRequest[reqKey].abort()
  6.     delete cacheRequest[reqKey]
  7.   }
  8. }
复制代码
3.在哀求拦截器里加入取消重复哀求的逻辑

之以是做成根据isAbort标识判断是否利用AbortController,是由于并不是全部的哀求都是需要取消重复哀求的,就像并不是全部的哀求都需要防抖节省一样,以是当我们有需要的时候,再加这个标识就好。
  1. const service = axios.create({
  2.   baseURL: hosts.server, // api 的 base_url
  3.   timeout: 50e3, // request timeout
  4. });
  5. service.interceptors.request.use(config => {
  6.     // isAbort - 是config里配置的是否清除相同请求的标识,不传则默认是不需要清除
  7.     const { url, method, isAbort= false } = config
  8.     if (isAbort) {
  9.         // 请求地址和请求方式组成唯一标识,将这个标识作为取消函数的key,保存到请求队列中
  10.         const reqKey = `${url}&${method}`
  11.         // 如果config传了需要清除重复请求的isAbort,则如果存在重复请求,删除之前的请求
  12.         abortCacheRequest(reqKey)
  13.         // 将请求加入请求队列,通过AbortController来进行手动取消
  14.         const controller = new AbortController()
  15.         config.signal = controller.signal
  16.         cacheRequest[reqKey] = controller
  17.     }
  18. })
复制代码
4.在相应拦截器里加入判断

假如哀求成功后,扫除cacheRequest里对应的存储;而且在error里判断,取消的哀求不做任何处理
  1. service.interceptors.response.use(res => {
  2.   // 请求成功,从队列中移除
  3.   const { url, method, isAbort = false } = response.config
  4.   if (isAbort) delete cacheRequest[`${url}&${method}`]
  5. }), error => {
  6.   if (isCancel(error)) {
  7.     // 通过AbortController取消的请求不做任何处理
  8.     return Promise.reject({
  9.       message: '重复请求,已取消'
  10.     })
  11.   }
  12. }
复制代码
5.利用

在调用接口的时候,增加一个isAbort的标识为true就能开启取消重复哀求的功能了
  1. //请求示例
  2. export function getList(data) {
  3.   return request({
  4.     url: '/list',
  5.     method: 'post',
  6.     data: data,
  7.     isAbort: true // 配置标识 如果该接口频繁请求 则会中断上次请求保留最新一次请求
  8.   })
  9. }
复制代码
效果图:

体验感极佳,status为canceled,都是被取消的哀求

小拓展: 

如何取消xhr的哀求:
  1. xhr.abort()
复制代码
如何取消fetch哀求:
  1. let controller = new AbortController();
  2. let signal = controller.signal;
  3. fetch(url, {signal});
  4. controller.abort(); // 取消请求
  5. //监听请求取消情况
  6. signal.addEventListener('abort',
  7.   () => console.log('abort!',signal.aborted)
  8. );
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

卖不甜枣

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表