防止重复发送 Ajax 请求


Posted in Javascript onFebruary 15, 2017

要考虑并理解 success, complete, error, timeout 这些事件的区别,并注册正确的事件,一旦失误,功能将不再可用;

不可避免地比普通流程要要多注册一个 complete 事件;

恢复状态的代码很容易和不相干的代码混合在一起;

推荐用主动查询状态的方式(A、B,jQuery 为例)或工具函数的方式(C、D)来去除重复操作,并提供一些例子作为参考:

A. 独占型提交

只允许同时存在一次提交操作,并且直到本次提交完成才能进行下一次提交。

module.submit = function() {
 if (this.promise_.state() === 'pending') {
 return
 }
 return this.promise_ = $.post('/api/save')
}

B. 贪婪型提交

无限制的提交,但是以最后一次操作为准;亦即需要尽快给出最后一次操作的反馈,而前面的操作结果并不重要。

module.submit = function() {
 if (this.promise_.state() === 'pending') {
 this.promise_.abort()
 }
 // todo
}

比如某些应用的条目中,有一些进行类似「喜欢」或「不喜欢」操作的二态按钮。如果按下后不立即给出反馈,用户的目光焦点就可能在那个按钮上停顿许久;如果按下时即时切换按钮的状态,再在程序上用 abort 来实现积极的提交,这样既能提高用户体验,还能降低服务器压力,皆大欢喜。

C. 节制型提交

无论提交如何频繁,任意两次有效提交的间隔时间必定会大于或等于某一时间间隔;即以一定频率提交。

module.submit = throttle(150, function() {
 // todo
})

如果客户发送每隔100毫秒发送过来10次请求,此模块将只接收其中6个(每个在时间线上距离为150毫秒)进行处理。

这也是解决查询冲突的一种可选手段,比如以知乎草稿举例,仔细观察可以发现:

编辑器的 blur 事件会立即触发保存;

保存按钮的 click 事件也会立即触发保存;

但是存在一种情况会使这两个事件在数毫秒内连续发生——当焦点在编辑器内部,并且直接去点击保存按钮——这时用 throttle 来处理是可行的。

另外还有一些事件处理会很频繁地使用 throttle,如: resize、scroll、mousemove。

D. 懒惰型提交

任意两次提交的间隔时间,必须大于一个指定时间,才会促成有效提交;即不给休息不干活。

module.submit = debounce(150, function() {
 // todo
})

还是以知乎草稿举例,当在编辑器内按下 ctrl + s 时,可以手动保存草稿;如果你连按,程序会表示不理解为什么你要连按,只有等你放弃连按,它才会继续。

============

更多记忆中的例子

方式 C 和 方式 D 有时更加通用,比如这些情况:

游戏中你捡到一把威力强大的高速武器,为了防止你的子弹在屏幕上打成一条直线,可以 throttle 来控制频率;

在弹幕型游戏里,为了防止你把射击键夹住来进行无脑游戏,可以用 debounce 来控制频率;

在编译任务里,守护进程监视了某一文件夹里所有的文件(如任一文件的改变都可以触发重新编译,一次执行就需要2秒),但某种操作能够瞬间造成大量文件改变(如 git checkout),这时一个简单的 debounce 可以使编译任务只执行一次。

而方式 C 甚至可以和方式 B 组合使用,比如自动完成组件(Google 首页的搜索就是):

当用户快速输入文本时(特别是打字能手),可以 throttle keypress 事件处理函数,以指定时间间隔来提取文本域的值,然后立即进行新的查询;

当新的查询需要发送,但上一个查询还没返回结果时,可以 abort 未完成的查询,并立即发送新查询;

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
jQuery 选择器理解
Mar 16 Javascript
JS格式化数字保留两位小数点示例代码
Oct 15 Javascript
js Array操作的最简短最容易理解方法
Dec 09 Javascript
jQuery实现页面滚动时动态加载内容的方法
Mar 20 Javascript
js检测iframe是否加载完成的方法
Nov 26 Javascript
jQuery Html控件基本操作(日常收集整理)
Mar 11 Javascript
利用js来实现缩略语列表、文献来源链接和快捷键列表
Dec 16 Javascript
Bootstrap的modal拖动效果
Dec 25 Javascript
Angular中$broadcast和$emit的使用方法详解
May 22 Javascript
使用vue实现简单键盘的示例(支持移动端和pc端)
Dec 25 Javascript
ng-zorro-antd 入门初体验
Dec 03 Javascript
详解微信小程序scroll-view横向滚动的实践踩坑及隐藏其滚动条的实现
Mar 14 Javascript
Input文本框随着输入内容多少自动延伸的实现
Feb 15 #Javascript
利用Jquery实现几款漂亮实用的时间轴(附示例代码)
Feb 15 #Javascript
js记录点击某个按钮的次数-刷新次数为初始状态的实例
Feb 15 #Javascript
Canvas 绘制粒子动画背景
Feb 15 #Javascript
jQuery插件jquery.kxbdmarquee.js实现无缝滚动效果
Feb 15 #Javascript
js控制按钮,防止频繁点击响应的实例
Feb 15 #Javascript
js代码延迟一定时间后执行一个函数的实例
Feb 15 #Javascript
You might like
PHP中exec函数和shell_exec函数的区别
2014/08/20 PHP
php类的自动加载操作实例详解
2016/09/28 PHP
php封装的数据库函数与用法示例【参考thinkPHP】
2016/11/08 PHP
PHP缓存工具XCache安装与使用方法详解
2018/04/09 PHP
PHP实现的CURL非阻塞调用类
2018/07/26 PHP
深入理解JavaScript系列(11) 执行上下文(Execution Contexts)
2012/01/15 Javascript
解决Extjs4中form表单提交后无法进入success函数问题
2013/11/26 Javascript
超炫的jquery仿flash导航栏特效
2014/11/11 Javascript
js读取csv文件并使用json显示出来
2015/01/09 Javascript
vue-router实现webApp切换页面动画效果代码
2017/05/25 Javascript
解决Vue打包之后文件路径出错的问题
2018/03/06 Javascript
javascript实现文件拖拽事件
2018/03/29 Javascript
Vue.js 实现数据展示全部和收起功能
2018/09/05 Javascript
JS 音频可视化插件Wavesurfer.js的使用教程
2018/10/31 Javascript
使用vuex较为优雅的实现一个购物车功能的示例代码
2019/12/09 Javascript
在antd Table中插入可编辑的单元格实例
2020/10/28 Javascript
[02:43]中国五虎出征TI3视频
2013/08/02 DOTA
Python爬取当当、京东、亚马逊图书信息代码实例
2017/12/09 Python
对python .txt文件读取及数据处理方法总结
2018/04/23 Python
解决tensorflow训练时内存持续增加并占满的问题
2020/01/19 Python
python3实现raspberry pi(树莓派)4驱小车控制程序
2020/02/12 Python
Python3 操作 MySQL 插入一条数据并返回主键 id的实例
2020/03/02 Python
无惧面试,带你搞懂python 装饰器
2020/08/17 Python
Python如何实现机器人聊天
2020/09/10 Python
vivo智能手机官方商城:vivo
2016/09/22 全球购物
迪卡侬印度官网:购买所有体育用品
2017/06/24 全球购物
韩国11街:11STREET
2018/03/27 全球购物
adidas澳大利亚官方网站:adidas Australia
2018/04/15 全球购物
运动会入场解说词
2014/02/07 职场文书
个人委托书怎么写
2014/04/04 职场文书
音乐幼师求职信
2014/07/09 职场文书
司机工作自我鉴定
2014/09/19 职场文书
交通局领导班子群众路线教育实践活动对照检查材料思想汇报
2014/10/09 职场文书
预备党员自我评价范文
2015/03/04 职场文书
ES6 解构赋值的原理及运用
2021/05/25 Javascript
python字典的元素访问实例详解
2021/07/21 Python