//伪代码如下
function fooClick(){
$('button').prop('disable',true);
$.ajax({
...
async:false, //同步
success: function(){
$('button').prop('disable',false);
...
},
error:funciton(){
$('button').prop('disable',false);
...
}
})
}
目的比较简单,点击后button变成不可点击,直到http响应完成,变回可以点击。
问题是: 如上代码,当ajax的async属性为false(即同步)时,短时间内快速连续点击3次button(即在第一个ajax还在pending的时候继续点2下button),会依次触发3次ajax请求,当然这3次请求都是等前一个ajax请求响应完成再发起另一次的
当我把ajax的async属性变成true(异步)时候,同样短时间内快速连续点击3次button,只会触发一次ajax请求。(这样的效果是我期望的)
问题是:为什么同步的情况下,click事情似乎被放进一个堆里面?
$('button').prop('disable', false);
引起repaint
repaint
和reflow
并不是执行到代码,就立即更新到dom
而是放到一个队列,脚本执行完毕一次执行完毕。代码错误
同步
执行
$('button').prop('disable', true);
引起repaint
不更新 dom 放到dom
更新队列。继续执行 同一个函数,执行 同步 ajax 。
同步 ajax 执行完毕,执行
$('button').prop('disable', false);
引起repaint
不更新 dom 放到dom
更新队列。整个代码执行完毕。
执行更新
dom
队列,dom
一次更新成 最后一个结果 也就是$('button').prop('disable', false)
。同步情况下,
dom
没有更新的情况下(在 第5步 之前) 你快速连续点击,点击几次就执行几次异步
执行
$('button').prop('disable', true);
引起repaint
不更新 dom 放到dom
更新队列。继续执行 同一个函数,执行 异步 ajax 。
代码执行完毕 执行更新
dom
队列,dom
更新成$('button').prop('disable', true);
异步
callback
执行$('button').prop('disable', false);
引起repaint
不更新 dom 放到dom
更新队列。异步
callback
执行完毕。执行更新
dom
队列,dom
更新成$('button').prop('disable', false)
。异步情况下,
dom
第一次更新在发出 ajax 请求后就执行了,你的感受来说,就是立即执行了,只能点击一次。建议
避免仅仅使用
dom
控制多次点击