防止重复发送 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 相关文章推荐
JavaScript XML操作 封装类
Jul 01 Javascript
基于mootools插件实现遮罩层新手引导
May 24 Javascript
判定是否原生方法的JS代码
Nov 12 Javascript
javascript修改表格背景色实例代码分享
Dec 10 Javascript
JS实现超简洁网页title标题跑动闪烁提示效果代码
Oct 23 Javascript
javascript Slip.js实现整屏滑动的手机网页
Nov 25 Javascript
ros::spin() 和 ros::spinOnce()函数的区别及详解
Oct 01 Javascript
ES6入门教程之Class和Module详解
May 17 Javascript
微信小程序之绑定点击事件实例详解
Jul 07 Javascript
详解angularjs实现echart图表效果最简洁教程
Nov 29 Javascript
javascript中this的用法实践分析
Jul 29 Javascript
Vue自定义表单内容检查rules实例
Oct 30 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
检测codeigniter脚本消耗内存情况的方法
2015/03/21 PHP
PHP实现更改hosts文件的方法示例
2017/08/08 PHP
[原创]PHP获取数组表示的路径方法分析【数组转字符串】
2017/09/01 PHP
控制打印时页眉角的代码
2007/02/08 Javascript
Prototype Array对象 学习
2009/07/19 Javascript
从零开始学习jQuery (十) jQueryUI常用功能实战
2011/02/23 Javascript
JavaScript判断一个URL链接是否有效的实现方法
2011/10/08 Javascript
三种方式获取XMLHttpRequest对象
2014/04/21 Javascript
struts2+jquery组合验证注册用户是否存在
2014/04/30 Javascript
浅析JavaScript 箭头函数 generator Date JSON
2016/05/23 Javascript
jQuery轮播图效果精简版完整示例
2016/09/04 Javascript
浅谈javascript:两种注释,声明变量,定义函数
2016/10/05 Javascript
javascript动画系列之模拟滚动条
2016/12/13 Javascript
Angular的$http的ajax的请求操作(推荐)
2017/01/10 Javascript
JS实现的简单下拉框联动功能示例
2018/05/11 Javascript
浅入深出Vue之组件使用
2019/07/11 Javascript
linux系统使用python获取内存使用信息脚本分享
2014/01/15 Python
python通过floor函数舍弃小数位的方法
2015/03/17 Python
Python3操作SQL Server数据库(实例讲解)
2017/10/21 Python
django-crontab实现服务端的定时任务的示例代码
2020/02/17 Python
离线状态下在jupyter notebook中使用plotly实例
2020/04/24 Python
HTML5拖拉上传文件的简单实例
2017/01/11 HTML / CSS
美国生日蛋糕店:Bake Me A Wish!
2017/02/08 全球购物
Harman Audio官方商店:购买JBL、Harman Kardon、Infinity和AKG
2019/12/05 全球购物
Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?
2014/07/27 面试题
电子商务专业毕业生工作推荐信
2013/11/17 职场文书
自我评价200字分享
2013/12/17 职场文书
顶岗实习计划书
2014/01/10 职场文书
《小鹰学飞》教学反思
2014/04/23 职场文书
新教师培训方案
2014/06/08 职场文书
微笑服务标语
2014/06/24 职场文书
弘扬焦裕禄精神走群众路线思想汇报
2014/09/12 职场文书
2015年医德考评自我评价
2015/03/03 职场文书
2015年财务部年度工作总结
2015/05/19 职场文书
redis数据结构之压缩列表
2022/03/21 Redis
详解Python中__new__方法的作用
2022/03/31 Python