编者按:本文作者舒丽琦,奇舞团前端开发工程师

在我们web开发过程中,很多地方需要我们取消重复的请求。但是哪种场合需要我们取消呢?我们如何取消呢?带着这些问题我们阅读本文。

阅读完本文,你将了解以下内容:

  • 需要取消重复请求的场景

  • 我们如何取消重复请求

  • axios如何取消重复的请求

  • 封装axios

  • 如何给开源的项目提供源码

  • 如何在本地调试npm包

提出问题

最近做的项目中,用的用户经常遇到这样的问题:

  • 用户频繁切换筛选条件去请求数据,初次的筛选条件数据量大。用的时间比较多。后面的筛选条件的数据量小。导致后面请求的数据先返回。内容先显示在页面上。但是等一段时间,初次(或者前面)的请求数据返回了, 会覆盖后面的请求的数据。这就导致了筛选条件和内容不一致的情况。

  • 用户点击了一次提交按钮,接口没有很快响应,导致页面没办法做逻辑语句判断的提示。用户觉得可能没提交上,便会快速又点了按钮几次。如果后端没有去重的判断,就会导致数据中有很多条重复的数据。

这些问题给用户的体验是很不友好的。那么取消无用的请求是很有必要的。

解决思路

我们用的请求库是axios。那么我们可以在请求的时候拦截请求判断当前的请求是否重复,如果重复我们就取消当前的请求。大致的实现过程如下:

我们把目前处于pending的请求存储(假如我们放在一个数组)起来。每个请求发送之前我们都要判断当前这个请求是否已经存在于这个数组。如果存在,说明请求重复了,我们就在数组中找到重复的请求并且取消。如果不存在,说明这个请求不是重复的,正常发送并且把这个请求api添加在数据中,等请求结束之后删除数组中的这个api。

我们这个解决思路有了,但是axios如何取消请求的呢?我们先来了解下

axios 如何取消请求

查看axios文档发现axios提供了两种取消请求的方法(http://www.axios-js.com/zh-cn/docs/#%E5%8F%96%E6%B6%88)

  • 第一种方法

    通过axios.CancelToken.source生成取消令牌token和取消方法cancel

    const CancelToken = axios.CancelToken;
    const source = CancelToken.source();
    axios.get('/user/12345', {cancelToken: source.token
    }).catch(function(thrown) {if (axios.isCancel(thrown)) {console.log('Request canceled', thrown.message);} else {// 处理错误}
    });
    axios.post('/user/12345', {name: 'new name'
    }, {cancelToken: source.token
    })
    // 取消请求 (消息参数是可选的)
    source.cancel('Operation canceled by the user.');
    
  • 第二种方式

    通过传递一个 executor 函数到 CancelToken 的构造函数来创建 cancel token

    const CancelToken = axios.CancelToken;
    let cancel;
    axios.get('/user/12345', {cancelToken: new CancelToken(function executor(c) {// executor 函数接收一个 cancel 函数作为参数cancel = c;})
    });
    // 取消请求
    cancel();
    

封装axios

解决取消请求的思路有了,取消请求的办法也有了,那么剩下的就是封装了

由于同事之前已经封装了axios——very-axios(https://github.com/verymuch/very-axios) (基于 axios 进行二次封装,更简单、更统一地使用 axios)。那么我们就这个基础上提一个pr吧。那么从现在开始我们就一步一步的来实现,这个过程包含了【如何给开源的项目贡献代码】【如何在本地调试npm】如果已经了解的同学可以直接略过。

准备工作

由于同事已经封装了axios并且已经开源了。那么我贡献代码的方式主要有两种:

  • 代码仓库的管理者给我们添加这个仓库的写入权限,如果这样,我们就可以直接提push。

  • 如果我们没有权限(大多数情况)。我们使用经典的fork & pull request 的方式来提交代码。

我们采用的第二种方式。我们去 very-axios(https://github.com/verymuch/very-axios) 把代码fork到自己的仓库(如果你还没有自己的github,需要自己注册下哦)。

那么你回到自己的github仓库下面就会看有一个一摸一样的项目

那么我们现在就可以git clone这个仓库的代码到本地,新建branch进行开发,就比如我新建了一个这样的branch:

现在已经有本地的代码了,但是我们如何本地化调试npm包呢?那就需要npm link 了

首先在我们要修改的npm 包中npm link:

之后我们会得到

/Users/shuliqi/.nvm/versions/node/v12.17.0/lib/node_modules/very-axios -> /Users/shuliqi/study/axios/very-axios

这意思就是我们把very-axios链接到全局的node_modules

然后我们进入我们my-project-of-axios 目录下面执行npm link very-axios 如图:

这意思就是very-axios被安装在my-project-of-axios 下面了。very-axios的修改都会同步到my-project-of-axios。就实现本地测试了。

我们在my-project-of-axios中的HelloWorld.vue文件中做列子。

如果这里看的不是很懂的同学可以看看这两篇文章:如何在本地调试npm包(https://github.com/allenGKC/Blog/issues/13)。如何使用 GitHub Flow 给开源项目贡献代码(https://juejin.im/post/6844903636863041550)

开始封装

准备工作完成了, 那我们开始封装的事情。根据我们之前的思路。我们采用axios 如何取消请求的第一种方式。

声明一个Map。用来存储每个请求的 标识 和 取消的函数

// 存储每个请求的标识和取消的函数
this.pendingAjax = new Map();

自定一个字段来让用户自己决定是否需要取消重复的请求

// 是否取消重复的请求
cancelDuplicated = false,

自定一个字段来让用户是否有全局的统一的设置重复标识的函数。如果没有设置全局的统一的函数,则默认是请求的method 和url作为重复的标识

// 生成重复标识的方式
duplicatedKeyFn,
this.duplicatedKeyFn = isFunction(duplicatedKeyFn) ? duplicatedKeyFn : (config) => `${config.method}${config.url}`;

添加请求

/*** 将请求添加到pendingAjax* @param {Object} config*/
addPendingAjax(config) {// 是否需要取消重复的请求if (!this.cancelDuplicated) returnconst veryConfig = config.veryConfig || {};const duplicatedKey = JSON.stringify({duplicatedKey: veryConfig.duplicatedKey || this.duplicatedKeyFn(config),type: REQUEST_TYPE.DUPLICATED_REQUEST,});config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => {// 如果pendingAjax中不存在当前请求,添加进去if (duplicatedKey && !this.pendingAjax.has(duplicatedKey)) {this.pendingAjax.set(duplicatedKey, cancel);}});
}

这里面我们可以使用duplicatedKey字段来让用户对单一请求自定义重复的标识。或者可以使用一个函数duplicatedKeyFn统一的让用户自定义重复的标识

删除请求

/*** 从pendingAjax中删除请求* @param {Object} config*/removePendingAjax(config) {// 是否需要取消重复的请求if (!this.cancelDuplicated) returnconst veryConfig = config.veryConfig || {};const duplicatedKey = JSON.stringify({duplicatedKey: veryConfig.duplicatedKey || this.duplicatedKeyFn(config),type: REQUEST_TYPE.DUPLICATED_REQUEST,});// 如果pendingAjax中存在当前请求, 取消当前请求并将其删除if (duplicatedKey && this.pendingAjax.has(duplicatedKey)) {const cancel = this.pendingAjax.get(duplicatedKey);cancel(duplicatedKey);this.pendingAjax.delete(duplicatedKey);}}

封装好了, 我们在哪里使用呢?肯定是在请求开始之前和请求完成之后使用。

在请求之前

// 拦截请求
this.axios.interceptors.request.use((config) => {// 在请求开始之前检查先前的请求this.removePendingAjax(config);// 将当前请求添加到pendingAjaxthis.addPendingAjax(config);// ...
});

在请求完成之后去掉该请求

// 拦截响应
this.axios.interceptors.response.use(response => {removePending(response)return response
}, error => {// ...
})

到现在已经完成了该有的功能, 但是取消请求的错误我们不该返回给用户。所以:

(err) => {
// 类型是否为重复请求
let isDuplicatedType;
try {const errorType = (JSON.parse(error.message) || {}).typeisDuplicatedType = errorType === REQUEST_TYPE.DUPLICATED_REQUEST;
} catch (error) {isDuplicatedType = false
}
if (isDuplicatedType) return;
}

我们在请求完成之后的err里面做一个判断,判断如果当前请求是取消的类型,我们就不返回给用户错误的提示信息。

总结

至此,完成了我们的封装。完成的pr地址:(https://github.com/verymuch/very-axios/pull/1)。本文测试npm包的项目地址:(https://github.com/shuliqi/my-project-of-axios)

最后

欢迎关注【前端瓶子君】✿✿ヽ(°▽°)ノ✿

欢迎关注「前端瓶子君」,回复「算法」,加入前端算法源码编程群,每日一刷(工作日),每题瓶子君都会很认真的解答哟!

回复「交流」,吹吹水、聊聊技术、吐吐槽!

回复「阅读」,每日刷刷高质量好文!

如果这篇文章对你有帮助,「在看」是最大的支持

》》面试官也在看的算法资料《《

“在看和转发”就是最大的支持

封装 axios 取消重复请求相关推荐

  1. axios delete有请求体吗_封装 axios 取消重复请求

    编者按:本文作者舒丽琦,奇舞团前端开发工程师 在我们web开发过程中,很多地方需要我们取消重复的请求.但是哪种场合需要我们取消呢?我们如何取消呢?带着这些问题我们阅读本文. 阅读完本文,你将了解以下内 ...

  2. 关于 axios 取消重复请求的分析

    前言 关于取消重复请求,最重要的是这么做的意义,而不在于代码的实现 其实,我觉得,绝大部分能够想到的应用场景,都可以通过防抖.节流方式实现,比如实时搜索,比如重复订单提交.比如上拉获取最新数据等 我们 ...

  3. 单页面axios_Axios封装之取消重复请求和接口缓存

    在平时的单页面项目里,大家肯定接触过axios库,一个易用.简洁且高效,使用Promise管理异步,告别传统callback方式的http库. 最近有个项目里接口调取的频率比较高,接口队列长,然后等待 ...

  4. axios取消接口请求

    自己碰到的问题,扒了很多文档才理清楚,当做是笔记记下来 说到取消接口请求,可能没碰到这样的坑冷不丁还有点懵,为什么会有取消请求这回事,既然决定要请求这个接口了又要取消它,岂不是有点画蛇添足的操作? 1 ...

  5. axios 拦截重复请求

    博客地址:http://www.globm.top/blog/1/detail/48 一直想封装一下 axios, 可以方便项目中使用,今天刚好 看到一位大佬的文章,就保存了过来,方便下次使用 axi ...

  6. php多次请求只执行最后一次,取消重复请求,只让最后一次请求通过

    axios 请求拦截 取消重复请求(多次重复异步,结束pending状态) 前端开发中,会涉及很多异步事件处理,页面展示的处理关系最密切的就是loading图层,但是loading交互在一些时候会不太 ...

  7. axios队列 vue_(十三 )Vue 封装axios(四种请求)及相关介绍

    Vue 封装axios(四种请求)及相关介绍 首先axios是基于promise的http库 promise是什么? 1.主要用于异步计算 2.可以将异步操作队列化,按照期望的顺序执行,返回符合预期的 ...

  8. 【跨域问题】Vue简单封装axios—解决post请求后端接收不到参数问题

    原因分析: 1. 传参数据没有序列化? 解决办法: [推荐] [推荐阅读] vue+axios+qs序列化 "三步解析"[含demo实例]- 代码篇 2. 服务端接受数据格式参数配 ...

  9. 【JS】Axios取消未完成请求解决Tab频繁切换数据问题

    一.场景描述 Tab切换频率较低.数据返回速度理想的情况下,几乎不用考虑这个问题.切换频率高如果不处理未完成的请求不仅会严重影响页面性能,由于浏览器并发请求限制,也可能会造成后续请求超时.另外一个较为 ...

最新文章

  1. java实验系统常用类,Java的常用系统类
  2. 超出网络bios会话限制_?老旧BIOS说再见,拯救者系列设置超简单
  3. mongodb java set_MongoDB Java常用操作
  4. C#DataTable2Json(附时间格式化)
  5. java 绘制sin函数图像_第11讲 数学软件Mathematica内置函数的使用规则
  6. 基于迁移学习的mini-imagenet数据分类实践
  7. debain服务器系统用什么,建站服务器系统用CentOS还是Debian 适合自己才好
  8. vbox NAT 设置端口映射(NAT+8080端口转发)
  9. WinEdt 参考文献格式
  10. 70个python毕设项目_这10个Python项目很有趣!
  11. Cisco Jabber 多个高危漏洞风险通告
  12. Java多线程系列--“JUC集合”02之 CopyOnWriteArrayList
  13. 投资不足半年,字节跳动退出李子柒签约公司“微念”
  14. JavaScript实现React实现网页转换成图片截屏下载
  15. RocketMQ(九)RocketMQ顺序消息
  16. matlab舍选法编程,利用舍选抽样法生成随机数.pdf
  17. 软件测试 pytest pytest的命名规则 用例的前后置 conftest.py 定制allure报告 @pytest.mark.parametrize()装饰器作数据驱动
  18. 科大讯飞麦克风阵列使用感受(六麦,XFM10621)
  19. 使用uglifyjs压缩JS文件
  20. 如何在 Linux 中使用 ripgrep (rg) 命令?

热门文章

  1. 赛马比赛:25匹马,5个赛道,选出跑的快的前几匹
  2. javascript第二天课程
  3. 华钜同创:都2022年了,你还在用那些老掉牙的选品方法???
  4. 用功譬若掘井,与其多绝掘数井,而皆不及泉,何若老守一井,力求泉而用之不竭乎?
  5. Pandas中melt()的使用
  6. lisp6 暖通cad_CAD迷你看图软件_CAD制图工具下载_免费CAD软件下载-华军纯净下载
  7. python爬取小说章节_python之如何爬取一篇小说的第一章内容
  8. 服装进销存软件哪个好?这5款是最受老板欢迎的,别错过
  9. 【Pandas-1】十分钟入门Pandas (上)
  10. UI设计前景如何?市场需要怎样的UI设计师?