axios的cancelToken
核心代码
import axios from 'axios'
// Base64可自行安装依赖或实现
import Base64 from './Base64'
class PendingPromiseStorage {
constructor() {
this._data = new Map()
}
setItem(payload) {
let { uid, item } = payload
this._data.set(uid, item)
}
getItem(uid) {
return this._data.get(uid)
}
removeItem(uid) {
this._data.delete(uid)
}
hasItem(uid) {
return this._data.has(uid)
}
cancelBefore(config) {
let { uid, url } = config
if (!this.hasItem(uid)) {
return
}
let item = this.getItem(uid)
let msg = `axios cancel (before cancel) ${url}`
item.cancel(msg)
this.removeItem(uid)
}
cancelAfter(config, cancel) {
let { uid, url } = config
if (!this.hasItem(uid)) {
return
}
let item = this.getItem(uid)
let msg = `axios cancel (after cancel) ${url}`
if (cancel !== item.cancel) {
setTimeout(() => {// 想看浏览器Network有记录,启用延迟
cancel(msg)
})
}
}
}
PendingPromiseStorage.getPendingUID = (config) => {
return Base64.encode(`${config.url}${config.method}${JSON.stringify(config.params)}${typeof config.data === 'string' ? config.data : JSON.stringify(config.data)}`)
}
const pendingPromiseStorage = new PendingPromiseStorage()
const interceptors = {
request: {
success(config) {
console.log('cancelToken:', config.cancelToken)
if (Object.hasOwnProperty.call(config, 'cancelToken')
&& (config.cancelToken === 'before' || config.cancelToken === 'after')
) {
let cancelToken = config.cancelToken
let uid = config.uid = PendingPromiseStorage.getPendingUID(config)
if (cancelToken === 'before') {
pendingPromiseStorage.cancelBefore(config)
}
let cancel = null
config.cancelToken = new axios.CancelToken(c => {
cancel = c
let item = {
uid,
createTime: Date.now(),
cancelToken,
cancel: c
}
if (
(cancelToken === 'before')
|| (cancelToken === 'after' && !pendingPromiseStorage.hasItem(uid))
) {
pendingPromiseStorage.setItem({ uid, item })
}
})
if (cancelToken === 'after') {
pendingPromiseStorage.cancelAfter(config, cancel)
}
}
return config
},
failed(error) {
let { config = {} } = error
pendingPromiseStorage.removeItem(config.uid)
return Promise.reject(error)
}
},
response: {
success(response) {
let { config } = response
pendingPromiseStorage.removeItem(config.uid)
return response
},
failed(error) {
let { config = {} } = error
pendingPromiseStorage.removeItem(config.uid)
return Promise.reject(error)
}
}
}
class Request extends axios.create {
constructor(config) {
super(config)
this.interceptors.request.use(interceptors.request.success, interceptors.request.failed)
this.interceptors.response.use(interceptors.response.success, interceptors.response.failed)
}
}
const instanceInterceptors = {
request: {
success(config) {
// TODO
return config
},
failed(error) {
return Promise.reject(error)
}
},
response: {
success(config) {
// TODO
return config
},
failed(error) {
return Promise.reject(error)
}
}
}
let instance = new Request({
name: 'Test-cancelToken',
baseURL: '/dev-api/',
timeout: 10000
})
instance.interceptors.request.use(instanceInterceptors.request.success, instanceInterceptors.request.failed)
instance.interceptors.response.use(instanceInterceptors.response.success, instanceInterceptors.response.failed)
export default instance
使用代码
export default {
methods: {
login() {
return request({
url: '/user/login',
method: 'post',
data: {
username: 'admin',
},
cancelToken: 'before'
// cancelToken: 'after'
})
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err)
})
}
}
}
// axios/lib/cancel/CancelToken.js
'use strict';
var Cancel = require('./Cancel');
function CancelToken(executor) {
if (typeof executor !== 'function') {
throw new TypeError('executor must be a function.');
}
/**
* 定义一个将来能执行取消请求的promise对象,当这个promise的状态为完成时(fullfilled),
* 就会触发取消请求的操作(执行then函数)。而执行resolve就能将promise的状态置为完成状态。
* 这里把resolve赋值给resolvePromise,就是为了在这个promise外能执行resolve而改变这个promise的状态
* 注意这个promise对象被赋值给CancelToken实例的属性promise,将来定义then函数就是通过这个属性得到promise
*/
var resolvePromise;
this.promise = new Promise(function promiseExecutor(resolve) {
resolvePromise = resolve;
});
/**
* 将CancelToken实例赋值给token
* 执行executor函数,将cancel方法传入executor,
* cancel方法可调用resolvePromise方法,即触发取消请求的操作
*/
var token = this;
executor(function cancel(message) {
if (token.reason) {
// 取消已响应 返回
return;
}
token.reason = new Cancel(message);
// 这里执行的就是promise的resolve方法,改变状态
resolvePromise(token.reason);
});
}
CancelToken.prototype.throwIfRequested = function throwIfRequested() {
if (this.reason) {
throw this.reason;
}
};
// 这里可以看清楚source函数的真面目
CancelToken.source = function source() {
var cancel;
var token = new CancelToken(function executor(c) {
// c 就是CancelToken中给executor传入的cancel方法
cancel = c;
});
return {
token: token,
cancel: cancel
};
};
module.exports = CancelToken;
// axios/lib/adapters/xhr.js
// 创建XHR对象
var request = new XMLHttpRequest()
// 模拟当前ajax请求
request.open(config.method.toUpperCase(), buildURL(config.url, config.params, config.paramsSerializer), true)
// 定义取消请求promise对象的then函数
if (config.cancelToken) { // 如果配置了cancelToken属性
// 当promise为完成态时,这个then函数执行,即执行取消请求
config.cancelToken.promise.then(function onCanceled(cancel) {
if (!request) {
return;
}
// 取消ajax请求
request.abort();
reject(cancel);
// Clean up request
request = null;
});
}
当使用new axios.cancelToken((c) => xx = c) 这里就是把一个执行函数放进去,然后在cancelToken中会new一个Promise 把promise的resolve丢到外面,然后再执行前面传进来的函数,我们传进来的函数中写一个参数就是c 这个c就是用来取消的,当c里面就是把这个resolve执行 执行了就会触发 promise的then 在then中使用xmlhttprequest.abort()的方法中断这个请求。
axios的cancelToken的更多相关文章
- axios 之cancelToken原理以及使用
看axios文档的时候发现cancelToken这个东东,这个是用来取消ajax请求的,一般原生的话用的是abort()这个方法.看到这玩意的第一感觉是用起来有点麻烦,但是看了内部实现,发现还是比较有 ...
- 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全攻略
随着 vuejs 作者尤雨溪发布消息,不再继续维护vue-resource,并推荐大家使用 axios 开始,axios 被越来越多的人所了解.本来想在网上找找详细攻略,突然发现,axios 的官方文 ...
- vue使用Axios做ajax请求
vue2.0之后,就不再对vue-resource更新,而是推荐使用axios 1. 安装 axios $ npm install axios 或 $ bower install axios 2. 在 ...
- HTTP库Axios
前面的话 本文将详细介绍HTTP库Axios 概述 Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中 [安装] 在Vue中使用,最好安装两个模块axios ...
- axios配合vue+webpack使用
1.安装引用: cnpm install axios --save-dev 2.在组件中引入: import axios from 'axios'; 3.使用示例: 执行GET请求: // 为给定 I ...
- 前端MVC Vue2学习总结(六)——axios与跨域HTTP请求、Lodash工具库
一.axios Vue更新到2.0之后宣告不再对vue-resource更新,推荐使用axios,axios是一个用于客户端与服务器通信的组件,axios 是一个基于Promise 用于浏览器和 no ...
随机推荐
- SSR,SSAO
3D Game Shaders For Beginners Screen Space Reflection (SSR)https://lettier.github.io/3d-game-shaders ...
- Unity通用渲染管线Shader日志输出工具
https://blog.uwa4d.com/archives/USparkle_Shaderlog.html
- JDBC之ResultSet和元数据
ResultSet 从名字上就可以看到是结果集,表示的是查询出来的结果集. JDBC用ResultSet来封装结果集,查询结果表的对象. 查询结果分为两种情况: 单值 单个结果,比如说SQL如下: s ...
- QCheckBox CSS样式
QCheckBox:!hover { color:white; border-radius:10px; border:1px solid rgb(170, 170, 127); background- ...
- 第八章 mysql的主从复制
mysql的主从复制 一 主从复制搭建 1. 准备三台主机 (这个是多实例) 3307 master3308 salve13309 salve2 2. master 节点设置 [mysqld] lo ...
- Unity生成AB包和加载AB包
unity生成AB包 生产AB包,编辑器脚本放在Editor文件夹下(切记) 如果你是PC包 BuildTarget.WebGL 后面要改成PC (BuildTarget.StandaloneWin ...
- oracle 数据恢复 回滚数据
1.查询你执行update 语句之前的数据 精确到什么时间 select * from 表名 as of timestamp to_timestamp('2017-07-21 17:16:38', ' ...
- flutter List使用
_tabbarTitile.map((e){ return Tab( text: e, ); }).toList(),
- qt中的一些对话框(个人备忘录)
一.标准对话框 1.对于颜色对话框 void MyWidget::on_pushButton_clicked() { QColorDialog dialog(Qt::red,this); dialog ...
- 2.21(html)