多语言展示
当前在线:1132今日阅读:75今日分享:44

如何防止重复发送 Ajax 请求?

一个简易的需求,点一个按钮,则向服务器请求资源,不作处理时,多次点击后会有很多个请求在等待。粗暴的解决方式是点一次就将按钮disable掉。请问一下有没有更好的办法,比如多点一次后自动down掉前一次请求?补充:不是一次请求,更类似于gmail的全站AJAX,刚用firebug看了一下gmail,发现重复请求时,之前的请求状态变为“Aborted”,并且不反回任何数据。请问是如何做到的呢?毕竟一般理解客户端AJAX发送后是不能终止的。
方法/步骤
1

独占型提交只允许同时存在一次提交操作,并且直到本次提交完成才能进行下一次提交。module.submit = function() {  if (this.promise_.state() === 'pending') {    return  }  return this.promise_ = $.post('/api/save')}

2

贪婪型提交无限制的提交,但是以最后一次操作为准;亦即需要尽快给出最后一次操作的反馈,而前面的操作结果并不重要。module.submit = function() {  if (this.promise_.state() === 'pending') {    this.promise_.abort()  }  // todo}比如某些应用的条目中,有一些进行类似「喜欢」或「不喜欢」操作的二态按钮。如果按下后不立即给出反馈,用户的目光焦点就可能在那个按钮上停顿许久;如果按下时即时切换按钮的状态,再在程序上用 abort 来实现积极的提交,这样既能提高用户体验,还能降低服务器压力,皆大欢喜。

3

节制型提交无论提交如何频繁,任意两次有效提交的间隔时间必定会大于或等于某一时间间隔;即以一定频率提交。module.submit = throttle(150, function() {  // todo})如果客户发送每隔100毫秒发送过来10次请求,此模块将只接收其中6个(每个在时间线上距离为150毫秒)进行处理。这也是解决查询冲突的一种可选手段,比如以知乎草稿举例,仔细观察可以发现:编辑器的 blur 事件会立即触发保存;保存按钮的 click 事件也会立即触发保存;但是存在一种情况会使这两个事件在数毫秒内连续发生——当焦点在编辑器内部,并且直接去点击保存按钮——这时用 throttle 来处理是可行的。另外还有一些事件处理会很频繁地使用 throttle,如: resize、scroll、mousemove。

4

懒惰型提交任意两次提交的间隔时间,必须大于一个指定时间,才会促成有效提交;即不给休息不干活。module.submit = debounce(150, function() {  // todo})还是以知乎草稿举例,当在编辑器内按下 ctrl + s 时,可以手动保存草稿;如果你连按,程序会表示不理解为什么你要连按,只有等你放弃连按,它才会继续。

5

记忆型var scrape = memoize(function(url) {  return $.post('/scraper', { 'url': url })})对于同样的参数,其返回始终结果是恒等的——每次都将返回同一对象。应用例子有编辑器,如粘贴内容时抓取其中的链接信息,memoize 用以保证同样的链接不会抓取两次。

6

累积型前几天处理自动完成事件时得到这个函数,发现也可以用在处理连续事件上,它能够把连续的多次提交合并为一个提交,比如:var request = makePile(5, function() {    $.post('/', { list: JSON.stringify([].slice.call(arguments)) })})// 连续发送五次 request({a:1}), request({a:2}), request({a:3}), request({a:4}), request({a:5})/* post =>list:[{'a':1},{'a':2},{'a':3},{'a':4},{'a':5}] */样例实现:var makePile = function(count, onfilter, onvalue) {  var values = [], id = function(value) { return value }  return function(value) {    values.push((onvalue || id).apply(this, arguments))    if (values.length === count) {      onfilter.apply(this, values)      values = []    }  }}

7

采样型这是最近重构时联想到的,一种和上面都不同的去重操作,可以应用在自动加载(timeline)行为控制上:autoload.listen(feeds, 'next', sample(3, function() {  this.enable() }))如果 sample 是固化的选择函数(n 选 1),它这实际上会这样工作:O-O-X-O-O-X但「自动加载」的应用可能想要的是(两次自动,一次手动):X-X-O-X-X-O对于这种情况,可以定义作为配置的选择函数来实现控制:options { sample: (n) => n % 3 !== 0 }即每个下一次加载完成之后, 每三次有两次对下一次加载实行自动加载。

注意事项

注意代码书写

推荐信息