axios取消请求的实践记录分享


Posted in Javascript onSeptember 26, 2018

问题的来源

用el-autocomplete远程获取数据时,点击输入框会触发第一次请求,然后输入搜索文字后会触发第二次请求,两次请求间隔较短,有时候会出现第二次请求比第一次请求先返回的情况,导致我们期望的第二次发送的请求返回的数据会被第一次请求返回的数据覆盖掉

解决思路

在发送第二次请求的时候如果第一次请求还未返回,则取消第一次请求,以保证后发送的请求返回的数据不会被先发送的请求覆盖。

axios官方文档取消请求说明

方法一:

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 {
 // handle error
 }
});

axios.post('/user/12345', {
 name: 'new name'
}, {
 cancelToken: source.token
})

// cancel the request (the message parameter is optional)
source.cancel('Operation canceled by the user.');

方法二:

const CancelToken = axios.CancelToken;
let cancel;

axios.get('/user/12345', {
 cancelToken: new CancelToken(function executor(c) {
 // An executor function receives a cancel function as a parameter
 cancel = c;
 })
});

// cancel the request
cancel();

不可行方案

注:本例采用的的axios的实例发送请求,其他情况未测试

初始方案A

请求时的代码如下:

/* 接口listApi.getList方法如下 */
const CancelToken = axios.CancelToken
const source = CancelToken.source()
getVideoList ({
 key
}) {
 return axiosInstance.post('/video/list', {
 key
 }, {
 cancelToken: source.token
 })
},
cancelRequest () {
 // 取消请求
 source.cancel()
}

/* 页面中获取列表的函数 */
getList (query, cb) {
 // 取消之前的请求
 listApi.cancelRequest()
 // 发送请求
 listApi.getVideoList({key: 'value'}).then(resp => {
 // handle response data
 }).catch(err => {
 if (axios.isCancel(err)) {
  console.log('Request canceled!')
 } else {
  this.$message.error(err.message)
 }
 })
}

此时chrome的Network面板并未发送getVideoList请求,控制台输出Request canceled!

原因猜想如下:

执行listApi.cancelRequest()时会将listApi.getVideoList({key: 'value'})返回的Promise状态置为reject,因此在执行listApi.getVideoList({key: 'value'})时并未发送请求,而直接执行catch块中的代码,在控制台输出Request canceled!。

改进方案B

将getList方案改造如下:

/* 页面中获取列表的函数 */
getList (query, cb) {
 // 发送请求
 listApi.getVideoList({key: 'value'}).then(resp => {
 // handle response data
 // 取消请求
 listApi.cancelRequest()
 }).catch(err => {
 if (axios.isCancel(err)) {
  console.log('Request canceled!')
 } else {
  this.$message.error(err.message)
 }
 })
}

此时发送两个请求时,会在第一个请求返回后取消别一个请求,并在控制台输出Request canceled!,但当取消请求触发后,再次触发getList方法时结果同方案A。

原因猜想如下:

用方法一触发取消请求后,此后触发该请求均返回同一个已经被reject的Promise,因此此例中请求取消后再次执行getList方法时并未发送getVideoList请求,而是在控制台直接输出Request canceled!

可行方案

可行方案C

代码如下:

/* 接口listApi.getList方法如下 */
const CancelToken = axios.CancelToken
let cancel
getVideoList ({
 key
}) {
 return axiosInstance.post('/video/list', {
 key
 }, {
 cancelToken: new CancelToken(function executor (c) {
  cancel = c
 })
 })
},
cancelRequest () {
 // 第一次执行videoService.cancelRequest()时还未发送getVideoList请求,会报错,添加如下判断
 if (typeof cancel === 'function') {
 // 取消请求
 cancel()
 }
}

/* 页面中获取列表的函数 */
getList (query, cb) {
 // 取消之前的请求
 listApi.cancelRequest()
 // 发送请求
 listApi.getVideoList({key: 'value'}).then(resp => {
 // handle response data
 }).catch(err => {
 if (axios.isCancel(err)) {
  console.log('Request canceled!')
 } else {
  this.$message.error(err.message)
 }
 })
}

此时重复发送多次`getVideoList请求时,会取消之前发送的请求保证返回数据为最后一次请求返回的数据。

以上这篇axios取消请求的实践记录分享就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript中的Screen屏幕对象
Jan 16 Javascript
详解angular 中的自定义指令之详解API
Jun 20 Javascript
easyui简介_动力节点Java学院整理
Jul 14 Javascript
详解从Vue.js源码看异步更新DOM策略及nextTick
Oct 11 Javascript
AngualrJs清除定时器遇到的坑
Oct 13 Javascript
vue组件间通信子与父详解(二)
Nov 07 Javascript
vue中的面包屑导航组件实例代码
Jul 01 Javascript
layUI实现前端分页和后端分页
Jul 27 Javascript
ES6常用小技巧总结【去重、交换、合并、反转、迭代、计算等】
Dec 21 Javascript
JS出现404错误原理及解决方案
Jul 01 Javascript
javascript实现支付宝滑块验证码效果
Jul 24 Javascript
jquery插件懒加载的示例
Oct 24 jQuery
Node.js模拟发起http请求从异步转同步的5种用法
Sep 26 #Javascript
在vue中获取token,并将token写进header的方法
Sep 26 #Javascript
基于axios 解决跨域cookie丢失的问题
Sep 26 #Javascript
vue项目使用axios发送请求让ajax请求头部携带cookie的方法
Sep 26 #Javascript
基于JavaScript实现一个简单的Vue
Sep 26 #Javascript
微信小程序授权登录及解密unionId出错的方法
Sep 26 #Javascript
vue根据进入的路由进行原路返回的方法
Sep 26 #Javascript
You might like
PHP 强制下载文件代码
2010/10/24 PHP
一个PHP缓存类代码(附详细说明)
2011/06/09 PHP
php在线代理转向代码
2012/05/05 PHP
php查找字符串出现次数的方法
2014/12/01 PHP
PHP中常见的缓存技术实例分析
2015/09/23 PHP
又十个超级有用的PHP代码片段
2015/09/24 PHP
详解laravel安装使用Passport(Api认证)
2018/07/27 PHP
让getElementsByName适应IE和firefox的方法
2007/09/24 Javascript
javascript 控制 html元素 显示/隐藏实现代码
2009/09/01 Javascript
javascript 通用loading动画效果实例代码
2014/01/14 Javascript
纯JS实现动态时间显示代码
2014/02/08 Javascript
JavaScript charCodeAt方法入门实例(用于取得指定位置字符的Unicode编码)
2014/10/17 Javascript
js简单实现标签云效果实例
2015/08/06 Javascript
Vuex模块化实现待办事项的状态管理
2017/03/15 Javascript
浅谈React 服务器端渲染的使用
2018/05/08 Javascript
JavaScript插入排序算法原理与实现方法示例
2018/08/06 Javascript
vue微信分享出来的链接点开是首页问题的解决方法
2018/11/28 Javascript
vue之a-table中实现清空选中的数据
2019/11/07 Javascript
vue实现移动端图片上传功能
2019/12/23 Javascript
Python实现动态添加类的属性或成员函数的解决方法
2014/07/16 Python
在Python中使用元类的教程
2015/04/28 Python
Python开发SQLite3数据库相关操作详解【连接,查询,插入,更新,删除,关闭等】
2017/07/27 Python
flask入门之表单的实现
2018/07/18 Python
使用Python完成15位18位身份证的互转功能
2019/11/06 Python
python时间与Unix时间戳相互转换方法详解
2020/02/13 Python
解决Jupyter NoteBook输出的图表太小看不清问题
2020/04/16 Python
与世界上最好的跑步专业品牌合作:Fleet Feet
2019/03/22 全球购物
波兰家居和花园家具专家:4Home
2019/05/26 全球购物
用你熟悉的语言写一个连接ORACLE数据库的程序,能够完成修改和查询工作
2012/06/11 面试题
招聘专员岗位职责
2014/03/07 职场文书
2014年党的群众路线学习心得体会
2014/11/05 职场文书
生产车间管理制度
2015/08/04 职场文书
优秀共产党员主要事迹材料
2015/11/05 职场文书
区域销售大会开幕词
2016/03/04 职场文书
CentOS7和8下安装Maven3.8.4
2022/04/07 Servers
Redis数据同步之redis shake的实现方法
2022/04/21 Redis