axios某一接口失败后不调用_axios 源码系列之如何取消请求

46d56b97826867270cc8b186dc2d7722.png

我们在前后端交互的过程中,通常是通过请求接口来实现的,而一个页面中的交互又非常复杂,例如需要多次频繁请求同一个接口,或者在接口还没返回时就要切换路由等。这些都需要对接口请求的时机或者请求接口之后进行处理,避免一些无用的请求或者接口返回顺序的差异。

  1. 防抖:在用户快速地交互过程中,只使用最后一次交互产生的数据,然后再发起请求,例如频繁的切换 tab,或者快速输入数据等;
  2. 锁状态:在上一个接口没有返回数据时,交互状态一直处于 loading 的锁定状态,直到数据正确返回或者超时等异常;
  3. 取消上一个请求:在发起下一个请求前,把之前的请求取消掉;

前两种方式,是在发起请求前进行控制,即控制发起请求的时机,而当请求发出之后则不再控制;而最终一种方式则是取消中断还在路上的请求,然后再发起一个新的请求,不用管发起的时机。这几种方式也要看业务的需要,选择最适合的即可。

31d5e4d9de8713b8adbc20dc547f1cd3.png

我们在之前的如何实现 axios 的自定义适配器 adapter文章里,略过了 axios 是如何主动取消当前请求的。今天我们就将一下在 axios 中如何取消之前发起的请求,源码中又是怎样实现的。

1. 主动取消之前发起的请求

我们先来看下 axios 中取消请求的用法:

const CancelToken = axios.CancelToken;// 返回两个字段,{ token, cancel }
// token用于表示某个请求,是一个Promise类型
// cancel是一个方法,当被调用时,则取消token注入的那个请求
const source = CancelToken.source();axios.get('/user/12345', {cancelToken: source.token, // 将token注入到请求中}).catch(function (thrown) {// 判断是否是因主动取消导致的if (axios.isCancel(thrown)) {console.log('Request canceled', thrown.message);} else {// handle errorconsole.error(thrown);}});axios.post('/user/12345',{name: 'new name',},{cancelToken: source.token,}
);// 主动取消请求
// cancel方法会把注入的同一个token的请求方法一并取消掉
// 上面的get和post请求都会被取消掉
// cancel the request (the message parameter is optional)
source.cancel('Operation canceled by the user.');

从 demo 上来看,用法很简单,token 和 cancel 的关系对应上即可。

官方例子中还有一种取消请求的方式,这个我们放在后面讲,更容易理解一些。

2. 源码解析

取消请求的方法在 https://github.com/axios/axios/tree/master/lib/cancel 的目录中,3 个文件:

  • Cancel: Cancel 类,message 和__CANCEL__属性,用于标识取消的某个请求;
  • isCancel: 判断当前参数是否是 Cancel 的实例;
  • CancelToken: 主流程,创建 Cancel 实例和取消的方法;

我们主要来看下 CancelToken 中的整个流程。

a23eebab1e9df273bece3c446eb5163d.png

2.1 source 方法

source 作为取消请求的入口,我们就先来看下 source 方法。

// 创建token和cancel方法
CancelToken.source = function source() {var cancel;// token为 CancelToken 的实例,包含 promise 和 reason 两个属性// 同时把 executor 中的参数给到 cancel// 即CancelToken有一个回调函数,而这个回调函数的参数也是一个函数// CancelToken怎么执行,我们接着看!var token = new CancelToken(function executor(c) {cancel = c;});return {token: token,cancel: cancel,};
};

2.2 CancelToken

CancelToken 用来取消请求,但我理解起来,思路非常的绕,我们一点点来剖析:

function CancelToken(executor) {if (typeof executor !== 'function') {throw new TypeError('executor must be a function.');}// 创建一个Promise的实例,// 当resolvePromise执行时,this.promise变为fulfilled状态var resolvePromise;this.promise = new Promise(function promiseExecutor(resolve) {resolvePromise = resolve;});// new一个实例时,会立即执行CancelToken的回调函数executor方法// executor的参数也是一个函数,即上面的cancel就是当前的cancel函数体// 当executor的回调函数cancel执行时,会给当前CancelToken创建一个reason属性,这个属性是Cancel的实例// 并执行resolvePromise方法,将reason实例穿进去;执行后this.promise变为fulfilled状态var token = this;executor(function cancel(message) {if (token.reason) {// Cancellation has already been requestedreturn;}token.reason = new Cancel(message);resolvePromise(token.reason);});
}

也就是说会先创建一个 CancelToken 的实例 token,同时,将 CancelToken 中回调函数的参数给到了 cancel。当 cancel 执行时,则 token 中的 promise 属性则会从 pending 状态变为 fulfilled 状态,那么 promise 上挂载的then()方法也就可以继续执行了。

2.3 adapter

在调用 cancel 方法后,请求中是怎么操作的呢?我们看下adapter/xhr.js中的代码:

if (config.cancelToken) {// config.cancelToken就是上面创建的token// 当token.promise变为fulfilled状态后,就可以执行后续的链式操作// Handle cancellationconfig.cancelToken.promise.then(function onCanceled(cancel) {if (!request) {return;}// 取消当前的请求request.abort();// 将Cancel的实例cancel给到rejectreject(cancel);// Clean up requestrequest = null;});
}

当我们使用 axios 的 catch 捕获内部抛出的异常时,就可以通过isCancel判断是否是因主动取消请求导致的异常:

axios.get('/user/12345', {cancelToken: source.token, // 将token注入到请求中}).catch(function (thrown) {// 判断是否是因主动取消导致的if (axios.isCancel(thrown)) {console.log('Request canceled', thrown.message);} else {// handle errorconsole.error(thrown);}});

现在再来看下 cancel 执行的整个流程,就会清晰流畅很多。

403f7e571346d372cc19c7cad696b039.png

3. 取消请求的另一种方式

我们在第 1 节还留着一个问题,axios 取消请求还有另一种方式,即直接使用 CancelToken 类。

  1. token: 我们在上面的 source()方法中就能看到,传给 axios 参数的 token 就是 CancenToken 的实例,这里直接使用new CancelToken()的返回值也是可以的;
  2. cancel: source()中的 cancel 就是 CancelToken 的回调函数 executor 的回调函数;
const CancelToken = axios.CancelToken;
let cancel;axios.get('/user/12345', {// CancelToken创建的cancelToken: new CancelToken(function executor(c) {// An executor function receives a cancel function as a parametercancel = c;}),
});// cancel the request
cancel();

其实我们发现,source()方法,只是给我们额外又封装了一下,简单的返回了 token 和 cancel,但本质还是 CancelToken 中的东西。

9585602b638ea7db5da3720b890722d3.png

4. 总结

在取消请求的过程中,token 要和 cancel 方法保持对应关系,即都在一个对象里;若其他的请求也要取消时,可以额外再生成一组 token 和 cancel。同时,这里还用到了 Promise 的一个机制,只有在当前 Promise 变更为 fulfilled 状态后,才能执行后面的 then 等操作。

更多文章欢迎查看我的博客:

蚊子的前端博客​www.xiabingbao.com
497ca9d2ff535ce1595a7c5094111537.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/428180.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

函数调用关系图如何画_程序是如何在 CPU 中运行的(二)

笔者能力有限,如果文中出现错误的地方,还请各位朋友能够给我指出来,我将不胜感激,谢谢~ 前言 在上一篇文章中《程序是如何在 CPU 中运行的(一)》笔者讲述了程序中一条一条指令以及一条一条数据是如何在 CPU 中运行的,在本文笔者将以 ARM Cortex M3 的内核为背景分析指令是…

电脑功耗监测_应急监测便携式VOC检测仪色谱分析仪原理解析

对目前越来越多的应急测试要求,应急监测便携式VOC检测仪色谱分析仪的发展日趋迅猛和成熟。而仪器的体积和重量一直制约着应急监测便携式VOC检测仪色谱分析仪的发展,Model 3200打破了传统色谱仪的桎梏,将便携式标气、便携式电脑工作站、在线VO…

L1-058 6翻了 (15 分)

题目复制不太好看,我直接给截图了,如上: 究其本源,pta L1的题目主要侧重于对字符串处理的考察,可以说拿下字符串,pta L1的题目百分之八十五的部分基本上都不会难倒你了,所以要在做题的时候注意积累。这里是…

N皇后问题12 · N-Queens

[抄题]: n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击。 给定一个整数n,返回所有不同的n皇后问题的解决方案。 每个解决方案包含一个明确的n皇后放置布局,其中“Q”和“.”分别表示一个…

L1-059 敲笨钟 (20 分)

题目截图如下,也可以跳转下方这个链接去pta平台自己测试一下: L1-059 敲笨钟 (20 分) 代码如下&#xff0c;部分关键注释已经在代码中标明: #include<bits/stdc.h> using namespace std; int main() {int n;string s;cin>>n;getchar(); //也可以使用cin.ignore()…

web前端表格css三个t的使用(thead,tbody,tfoot)

其实从这三个词的翻译上&#xff0c;也可以知道他们的使用用途&#xff1a; thead&#xff08;表格头&#xff09;tbody&#xff08;表格主体&#xff09;tfoot &#xff08;表尾&#xff09; 话不多说&#xff0c;先上效果图: 具体使用看见代码演示: <html> <head…

Vue框架之条件与循环的使用

如果是初学者的话&#xff0c;这里先给你一个基础知识的框图&#xff0c;可以了解一下下面代码的由来。 也可以选择我这个链接Vue条件与循环跳转到Vue官网进行学习。 上面是Vue的一个简单案例&#xff0c;不要急&#xff0c;进阶版来了&#xff0c;通过这个框架应用到你的表格…

git连接jenkins_开普勒云平台:如何配置gitlab与Jenkins

一、Kplcloud是什么?kplcloud是一个基于Kubernetes的轻量级PaaS平台&#xff0c;通过可视化的界面对应用进行管理&#xff0c;降低应用容器化的对度&#xff0c;从而减少应用容器化的时间成本。Kplcloud已在宜信服务于宜人财富等多个团队&#xff0c;稳定运行了近两年&#xf…

Eclipse查找文件存储路径

1.打开Eclipse&#xff0c;去找导航栏 2.点击file 3.点击properties 4.即可看到存储路径 5.可以点击存储路径找到该文件在电脑的储存位置 从此上传作业&#xff0c;找不到文件位置不再是烦恼。

专业对不对口重要吗_应届生求职,专业对口到底重不重要?

18年&#xff0c;智联招聘发布的《2018年大学生求职指南》显示&#xff0c;近四成毕业生就业岗位和在校专业不对口。同时&#xff0c;LinkedIn&#xff08;领英&#xff09;通过调查15万份用户档案分析发现&#xff0c;第一份工作的专业对口比例&#xff0c;95后只有28.8%。&am…

Xml的使用

关于xml的学习入门&#xff0c;下面的就足够了 话不多说&#xff0c;先上图 主要注释已经附在了代码里&#xff1a; 这是独立执行的xml文件&#xff0c;未关联css和XSL文件&#xff0c;只会显示出一棵数据树。 至于详细的使用&#xff0c;我都附在了代码注释里&#xff0c;可以…

C++中的位运算

最近在刷天梯题的时候&#xff0c;发现了<<和>>这两个运算&#xff0c;刚见到的时候简直一脸懵逼&#xff0c;觉得自己很菜&#xff0c;经过自己查找资料&#xff0c;发现原来这两个小东西是位运算符呀。为加深自己的印象&#xff0c;总结如下: 话不多说&#xff0…

node 更新_被创造者嫌弃,Node.js 如何应对来自 Deno 的挑战

(给前端大全加星标&#xff0c;提升前端技能)转自&#xff1a;OSC开源社区JavaScript 运行时 Node.js 于日前更新到了 15 版本&#xff0c;该软件自发布至今已走过了 11 年的岁月。但在今年 5 月&#xff0c;其竞争对手 Deno 也发布了 1.0 版本。Deno 是一个 Javascript/TypeS…

L1-046 整除光棍 (20 分)

这道题的解题过程真是一波三折&#xff0c;也真是发现人外有人&#xff0c;天外有天&#xff0c;好多神人真是。 原题如下图&#xff0c;也可点击这个链接到原题自己测试光棍原题链接: 一开始做的时候的想法&#xff1a;so easy&#xff0c;虽然看到了题目中提示s可能超级大…

uci数据集_数据分析找不到数据集?快来看这个盘点

前言数据集相对于机器学习而言是至关重要的&#xff0c;可以说好的数据集是成功的一半。但是&#xff0c;我们很难找到一个特定的数据集来解决各种机器学习问题&#xff0c;甚至是进行实验。因而找到合适的数据集是一件很难的事情&#xff0c;接下来我们就盘点一下一些优质的数…

git保留两个repo的commit并进行合并

以往的合并时首先要删除repo的.git文件夹&#xff0c;然后重新add-commit-push。带来的问题是会丢失某一个仓库的提交信息&#xff0c;不利于时光倒退。经过摸索终于实现了保留两个仓库提交信息的合并方法。介绍如下&#xff1a; 比如要将DownloadPicsBySeleniumAndPhantomJS这…

安利一款编辑神器——Markdown

经常使用word或者那些浏览器自带编辑器的你可能会和我有时候遇到一样的烦恼&#xff0c;调整格式可真是不容易&#xff0c;如果你也有同样的烦恼&#xff0c;不妨可以试一下Markdown&#xff0c;值得你拥有哈。 Markdown的使用 1.安装使用篇 a.首先安装软件&#xff0c;然后创…

一个项目部署多个节点会导致锁失效么_Redis分布式锁

分布式锁在很多场景中是非常有用的原语&#xff0c; 不同的进程必须以独占资源的方式实现资源共享就是一个典型的例子。有很多分布式锁的库和描述怎么实现分布式锁管理器(DLM)的博客,但是每个库的实现方式都不太一样&#xff0c;很多库的实现方式为了简单降低了可靠性&#xff…

GIT_服务器与本地环境构建

linux安装git包 很多yum源上自动安装的git版本为1.7&#xff0c;这里手动编译重新安装1&#xff1a;安装依赖包yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker2&#xff1a;删除已有的gityum remove git3&#xff1a…

Maven项目的基本创建步骤

先来个自己笔记的图片备忘一下&#xff0c;如果以后有时间再慢慢更新详细。