<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="checkbox" id="bigger_view" name="bigger_view" value="bigger_view" /><label for="bigger_view">切换</label>
</body>
<script>
var bigger_view = document.querySelector("#bigger_view")
var is_runing = false
bigger_view.onchange = ()=>{
if(is_runing){
return
}
is_runing = true
bigger_view.disabled = true
run_task(()=>{
is_runing = false
bigger_view.disabled = false
})
}
function run_task(callback){
console.log("is_runing")
for(var i=0; i<999999999*4; i++){
}
callback("finish")
}
</script>
</html>
以上代码,点击 checkbox 后(此时 run_task 还未完成)快速再次点击,run_task 会执行两次,请问大家这是为什么呢?
你可以添加一个点击事件:
可以看到,每次点击的时候
disabled
都是false
,这是由于「事件循环」,就像 AI 说的那样。简单来说,浏览器运行 JS 时,会保存一个任务队列,主线程空闲时会不断取出队列中的任务并运行。更详细、更准确的描述请参考网上的资料。
将长 for 循环改为更加准确的 while 循环并控制它阻塞 5 秒:
点击 checkbox,等待 2 秒再次点击,将产生如下结果:
当你点击 checkbox 并触发 onchange 事件时,onchange 函数不会立即运行,而是将这个函数作为一个任务添加到任务队列中。由于第一个 onchange 事件还没有运行完成,所以第二个 onchange 函数要等第一个运行完才能执行。而第一个函数运行完成时,已经将 disabled 设置为 false 了。