防止重复发送 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和PHP实现类似360功能开关效果
Feb 12 Javascript
JS+CSS实现感应鼠标渐变显示DIV层的方法
Feb 20 Javascript
JavaScript中的闭包介绍
Mar 15 Javascript
js实现两点之间画线的方法
May 12 Javascript
jquery限定文本框只能输入数字(整数和小数)
Jan 08 Javascript
Boostrap入门准备之border box
May 09 Javascript
Node.js+Express配置入门教程详解
May 19 Javascript
vue2.0构建单页应用最佳实战
Apr 01 Javascript
JQuery.dataTables表格插件添加跳转到指定页
Jun 09 jQuery
详解React Native 采用Fetch方式发送跨域POST请求
Nov 15 Javascript
JS中创建自定义类型的常用模式总结【工厂模式,构造函数模式,原型模式,动态原型模式等】
Jan 19 Javascript
JS数组方法join()用法实例分析
Jan 18 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编程每天必学之验证码
2016/03/03 PHP
PHP程序中的文件锁、互斥锁、读写锁使用技巧解析
2016/03/21 PHP
ZendFramework2连接数据库操作实例
2017/04/18 PHP
PHP实现重载的常用方法实例详解
2017/10/18 PHP
JS事件在IE与FF中的区别详细解析
2013/11/20 Javascript
js数组与字符串的相互转换方法
2014/07/09 Javascript
javascript复制粘贴与clipboardData的使用
2014/10/16 Javascript
jquery.cookie.js使用指南
2015/01/05 Javascript
Javascript实现多彩雪花从天降散落效果的方法
2015/02/02 Javascript
JavaScript中的this引用(推荐)
2016/08/05 Javascript
bootstrap的常用组件和栅格式布局详解
2017/05/02 Javascript
JavaScript简单实现关键字文本搜索高亮显示功能示例
2018/07/25 Javascript
angularjs的单选框+ng-repeat的实现方法
2018/09/12 Javascript
详解React 服务端渲染方案完美的解决方案
2018/12/14 Javascript
nodejs处理tcp连接的核心流程
2021/02/26 NodeJs
[01:11:46]DOTA2-DPC中国联赛 正赛 iG vs Magma BO3 第一场 2月23日
2021/03/11 DOTA
简单了解为什么python函数后有多个括号
2019/12/19 Python
Python+OpenCV实现将图像转换为二进制格式
2020/01/09 Python
Python文字截图识别OCR工具实例解析
2020/03/05 Python
Java ExcutorService优雅关闭方式解析
2020/05/30 Python
Python利用Xpath选择器爬取京东网商品信息
2020/06/01 Python
python中time包实例详解
2021/02/02 Python
HTML5 canvas 基本语法
2009/08/26 HTML / CSS
HTML5 贪吃蛇游戏实现思路及源代码
2013/09/03 HTML / CSS
2013年办公室秘书的个人自我鉴定
2013/10/24 职场文书
创伤外科专业推荐信范文
2013/11/19 职场文书
国际会议邀请函范文
2014/01/16 职场文书
艺校音乐专业自我鉴定范文
2014/03/01 职场文书
工程资料员岗位职责
2014/03/10 职场文书
演讲比赛的活动方案
2014/08/28 职场文书
政府班子四风问题整改措施思想汇报
2014/10/08 职场文书
党员批评与自我批评
2014/10/15 职场文书
2015年小学体育教师工作总结
2015/10/23 职场文书
Java8 CompletableFuture 异步回调
2022/04/28 Java/Android
介绍一下28个JS常用数组方法
2022/05/06 Javascript
SpringBoot详解执行过程
2022/07/15 Java/Android