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

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

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

我们在之前的如何实现 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 中的整个流程。

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 执行的整个流程,就会清晰流畅很多。

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 中的东西。

4. 总结

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

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

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

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

  1. axis2 webservice入门学识(JS,Java,PHP调用实例源码)

    来源:http://www.myexception.cn/web/952419.html axis2 webservice入门知识(JS,Java,PHP调用实例源码) 背景简介 最近接触到一个银行接 ...

  2. org.reflections 接口通过反射获取实现类源码研究

    org.reflections 接口通过反射获取实现类源码研究 版本 org.reflections reflections 0.9.12 Reflections通过扫描classpath,索引元数据 ...

  3. mutations vuex 调用_Vuex源码学习(六)action和mutation如何被调用的(前置准备篇)...

    前言 Vuex源码系列不知不觉已经到了第六篇.前置的五篇分别如下: 长篇连载:Vuex源码学习(一)功能梳理 长篇连载:Vuex源码学习(二)脉络梳理 作为一个Web前端,你知道Vuex的instal ...

  4. 2023 QQ强制聊天加好友临时会话接口跳转单页HTML源码

    功能: 跳转QQ聊天界面:支持已开启临时会话的QQ用户进行聊天. 跳转加好友界面:解决了QQ设置不允许被搜索后无法加好友的问题. WPA临时会话:可通过网页直接跳转至聊天界面,与第一个按钮实现相似的功 ...

  5. CTP综合交易平台接口-程序化交易编程模板(VC源码)

    期货程序化VC++ vs2008代码,自己只要编写交易策略部分即可,简单方便 动态行情.任意分钟K线.Tick数据自维护,自动收盘, 从文件brokers.xml找期货公司代码 直连期货公司交易服务器 ...

  6. 通达信收费接口查询可申购新股c++源码分享

    有很多股民在做股票交易时为了实现盈利会借助第三三方炒股工具帮助自己,那么通达信收费接口就是人们常用到的,今天小编来分享一下通达信收费接口查询可申购新股c++源码: std::cout << ...

  7. 分享股票level2接口的量价趋势指标源码

    分享股票level2接口的量价趋势指标源码: 价趋势:MA(C,3)LINETHICK2 COLORGRAY; AMOL:=LOG(MA(AMO/C/100,M)); AMOH:=LOG(MA(AMO ...

  8. 修复登录接口社区论坛微信小程序源码下载-支持多种发帖模式超强社区

    这是一款社区论坛小程序源码 内涵强大的功能 支持多种多样的发帖模式 比如发图文,发语音,发涂鸦,发视频等 另外也可以设置为只能会员才可以发 另外还拥有礼物功能,可以对发帖人打赏,礼物等都可以自定义 另 ...

  9. 易语言操作java窗口,易语言调用JAVA源码

    易语言调用JAVA源码 @510835147.版本 2 .支持库 Javalib .支持库 spec .程序集 窗口程序集1 .程序集变量 jvm, Java虚拟机 .程序集变量 java, Java ...

最新文章

  1. erlang精要(3)-变量、原子与布尔代数
  2. iNOC产品部-杨辉三角的变形
  3. 3DSMAX和ZBRUSH打造神秘性感美女
  4. RhinoMarine v4.0.3 plugin for Rhinoceros 船艇设计分析
  5. phpredis中文手册
  6. vue 使用flowplayer_Flowplayer视频播放插件
  7. 分而治之——最大子列和
  8. service常驻后台
  9. 机器学习概念西洋跳棋
  10. 用母函数(生成函数)求解整数拆分问题
  11. 2021中国开源优秀人物榜出炉!
  12. Photoshop学习(二):换色
  13. java 庖丁解牛api_重磅|庖丁解牛之——Flutter for Web
  14. 常见Andriod游戏破解搜索关键字
  15. python把手机做电脑摄像头
  16. 计算机科学引论英文精编pdf,计算机科学引论英文版.pdf
  17. Openwrt编译feeds机制
  18. python五角星教程_绘制五角星_清华尹成python入门教程_少儿编程视频-51CTO学院
  19. Unity光照效果_自发光动态改变并影响环境
  20. Python常用模块——随机函数(random)

热门文章

  1. python向dict里添加_Python有条件地向Dict添加键
  2. HttpURLConnection, Android访问网络,实用demo
  3. Android 隐藏状态栏,沉浸式状态栏,状态栏背景色,状态栏字体色,透明状态工具类
  4. pd怎么卸载linux系统,parallels desktop11怎么卸载?parallels desktop11卸载方法
  5. while语法php格式,PHP While 循环
  6. 计算机快捷键知识点,电脑常用快捷键基础的知识点(12页)-原创力文档
  7. mybatis3 类型别名
  8. oracle 邮件过程,oracle 发邮件 存储过程
  9. 1. 栈和队列的数组实现
  10. Bugku杂项-convert