axios 之cancelToken原理以及使用
看axios文档的时候发现cancelToken这个东东,这个是用来取消ajax请求的,一般原生的话用的是abort()这个方法。看到这玩意的第一感觉是用起来有点麻烦,但是看了内部实现,发现还是比较有意思的,今天就来分享一下。
基本使用
我们先来看看基本用法:
var CancelToken = axios.CancelToken;
var source = CancelToken.source();
axios.get('/user/12345', {//get请求在第二个参数
cancelToken: source.token
}).catch(function(thrown) {
});
axios.post('/user/12345', {//post请求在第三个参数
name: 'new name'
}, {
cancelToken: source.token
});
source.cancel('不想请求了');
注意,get请求的时候,cancelToken是放在第二个参数里;post的时候,cancelToken是放在第三个参数里。
我们可以发现,它要先引用axios.CancelToken,然后调用source()方法,会产生一个token和cancel,它的内部到底如何实现,这样做的目的是什么?
源码分析
现在我们来看看cancelToken的源码:
'use strict';
var Cancel = require('./Cancel');
/**
* A `CancelToken` is an object that can be used to request cancellation of an operation.
*
* @class
* @param {Function} executor The executor function.
*/
function CancelToken(executor) {
if (typeof executor !== 'function') {
throw new TypeError('executor must be a function.');
}
var resolvePromise;
this.promise = new Promise(function promiseExecutor(resolve) {
resolvePromise = resolve;
});
var token = this;
executor(function cancel(message) {
if (token.reason) {
// Cancellation has already been requested
return;
}
token.reason = new Cancel(message);
resolvePromise(token.reason);
});
}
/**
* Throws a `Cancel` if cancellation has been requested.
*/
CancelToken.prototype.throwIfRequested = function throwIfRequested() {
if (this.reason) {
throw this.reason;
}
};
/**
* Returns an object that contains a new `CancelToken` and a function that, when called,
* cancels the `CancelToken`.
*/
CancelToken.source = function source() {
var cancel;
var token = new CancelToken(function executor(c) {
cancel = c;
});
return {
token: token,
cancel: cancel
};
};
module.exports = CancelToken;
通过源码我们可以发现,CancelToken这个类初始化的时候需要传递一个方法executor,并且它的内部新建了一个promise,最关键的是,它把promise的resolve方法控制权放在了executor方法里面!这种操作代表什么意思?我们看一个小例子:
let resolveHandle;
new Promise((resolve)=>{
resolveHandle=resolve;
}).then((val)=>{
console.log('resolve',val);
});
resolveHandle('ok');
上面的例子中,我们用resolveHandle获取了一个promise的resolve方法的控制权,这样,我们就可以在外部控制这个promise的成功了。要知道new Promise返回的对象是无法从外部决定它成功还是失败的。
现在来看看source这个方法,我们可以看到,它new了一个CancelToken对象,并传了一个方法executor;采用相同的手法,用cancel变量将executor方法的变量c的控制权拿出来了,那么这个变量c又代表啥呢?
变量c正是我们前面说到的在CancelToken初始化时,传入executor方法的,也即:
function cancel(message) {
if (token.reason) {
// Cancellation has already been requested
return;
}
token.reason = new Cancel(message);
resolvePromise(token.reason);
}
也就是说cancel代表的是上面的这个方法,有了这个方法,就可以在外部控制CancelToken内部的promise对象了。
在source方法中,除了cancel,还有一个token,这个token是CancelToken类的一个实例,可以访问到内部的promise。
因此CancelToken类如此封装的主要目的就是为了能够分离promise和resolve方法,让用户可以自己调用resolve方法。一旦resolve后,就会触发promise的then方法,现在看看内部promise后的then方法是什么:
if (config.cancelToken) {
// Handle cancellation
config.cancelToken.promise.then(function onCanceled(cancel) {
if (!request) {
return;
}
request.abort();
reject(cancel);
// Clean up request
request = null;
});
}
上面是xhr.js的关于cancelToken部分相关代码,可以看到,当用户调用cancel后,就会立即执行abort方法取消请求,同时调用reject让外层的promise失败。
axios 之cancelToken原理以及使用的更多相关文章
- 如何实现 axios 的自定义适配器 adapter
Axios 是一个非常优秀的基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中.并且提供了很多便捷的功能,例如: 支持 Promise API 拦截请求和响应 转换请求数据和 ...
- axios二次封装的几种方法
一.用Class方法 import axios from "axios"; declare var Promise: any; export class Request { sta ...
- vue自动完成搜索功能的数据请求处理
在现在的互联网世界里,自动完成的搜索功能是一个很常见的功能.比如百度.搜狗.360搜索 ... 功能描述一下大概是这个样子的:有一个搜索框,用户在里面输入要查询的条件,系统会“智能”判断用户输完了,然 ...
- vue+elementui搭建后台管理界面(7 vuex和mockjs的使用)
将权限管理应用到系统,首先做好登录, 点击登录按钮后,触发以下动作 vuex 中的 login 动作,设置 cookie vuex 中的 getuserinfo , 获取权限.用户名.头像等 由于目前 ...
- axios 重复点击利用CancelToken阻止请求多次发送
import axios from 'axios'; axios.defaults.timeout = 5000; axios.defaults.baseURL =''; let pending = ...
- axios 内部原理学习记录
前提:一次面试被问到了,axios有什么特点,对比一下ajax.答的很不满意. axios是一个基于Promise的http请求库,可用于浏览器和 Node.可以说是目前最为常用的http库,有必要了 ...
- vue使用axios发送post请求时的坑及解决原理
前言:在做项目的时候正好同事碰到了这个问题,问为什么用axios在发送请求的时候没有成功,请求不到数据,反而是报错了,下图就是报错请求本尊 vue里代码如下: this.$http.post('/ge ...
- 终于明白了vue使用axios发送post请求时的坑及解决原理
前言:在做项目的时候正好同事碰到了这个问题,问为什么用axios在发送请求的时候没有成功,请求不到数据,反而是报错了,下图就是报错请求本尊 vue里代码如下: this.$http.post('/ge ...
- 理解 ajax、fetch和axios
背景 ajax fetch.axios 优缺点 ajax基于jquery,引入时需要引入庞大的jquery库,不符合当下前端框架,于是fetch替代了ajax 由于fetch是比较底层,需要我们再次封 ...
随机推荐
- Docker如何制作镜像-Dockerfile的使用
1:什么是Dockerfile Dockerfile是一个文本文档,可以通过docker build 命令构建成一个镜像. 我们可以在Dockerfile中定义一系列的命令,构建出我们想要的镜像. 想 ...
- 编写Java程序,使用JDialog构造登录窗体
返回本章节 返回作业目录 需求说明: 实现思路: 定义用户信息实体类User. 创建LoginDemoStart主类,初始化UI. 从UI获取用户信息并保存到User实体. 实现代码:
- 基于GO语言的PBFT共识算法
最近采用GO语言实现了一个PBFT共识算法的demo,主要用于展示算法的核心逻辑 github地址:https://github.com/w3liu/consensus/tree/master/pbf ...
- 03.python封装与解构
封装与结构 基本概念 t1 = 1, 2 print(type(t1)) # 什么类型 t2 = (1, 2) print(type(t2)) Python等式右侧出现逗号分隔的多值的时候,就会将这几 ...
- 您应该知道的35个绝对重要的Linux命令
https://mp.weixin.qq.com/s?__biz=MzU3NTgyODQ1Nw==&mid=2247499293&idx=2&sn=1353b78d6ad01d ...
- 深入谈谈 Java IOC 和 DI
1.前言 不得不说, IOC和DI 在写代码时经常用到.还有个就是在面试时 ,面试官老喜欢问 IOC 和DI是什么的问题,都快被问吐了, 可是,仍然会让许多人说的支支吾吾. 为什么? 第一,因为这个知 ...
- linux 设置root 密码
指令意思: sudo -i 是 切换到root权限 ,如果没有密码,则直接可以操作,有密码则会要求输入密码 sudo passwd root 是修改密码指令 ,回车后 提示输入新密码 新密码需要输 ...
- 微信小程序组建通信
子组件传递父组件需要用到triggerEvent方法,当子组件(自定义组件)点击button的时候调用triggerEvent方法传递一些数据,首先第一个属性为自定义名称(myevent)对应父组件( ...
- 使用Eclipse新建项目
如果图片损坏,点击查看: https://www.toutiao.com/i6496078011538866702/ 出现"新建"对话框,输入mavem 点击创建"简单M ...
- 刨根问底: Kafka 到底会不会丢数据?
大家好,我是 华仔, 又跟大家见面了. 上一篇作为专题系列的第二篇,从演进的角度带你深度剖析了关于 Kafka 请求处理全流程以及超高并发的网络架构设计的实现细节,今天开启第三篇,我们来聊聊 Kafk ...