setInterval在Event loop中的行为疑问:为何代码输出与预期不符?
为什么setInterval的回调只执行一次在End之后?
先看你的代码:
console.log("Start"); setInterval(function() { console.log("setInterval"); }, 5000); let date = new Date(); while(new Date() - date <= 10000) {} console.log("End");
核心原因:浏览器对setInterval的任务队列去重机制
JavaScript的事件循环里,定时器的回调会在到期时被推入任务队列,但如果同一个setInterval的回调已经在任务队列里等待执行,浏览器不会重复添加这个回调,防止任务队列被大量重复的定时器回调塞满。
一步步拆解执行流程:
- 首先同步执行
console.log("Start"),输出Start。 - 调用
setInterval,浏览器注册一个间隔为5秒的定时器,记录下回调函数。 - 进入while循环,主线程被完全阻塞10秒,期间无法处理任何任务队列里的回调:
- 第5秒时,定时器第一次到期,浏览器检查任务队列,发现没有该setInterval的回调等待,于是把回调推入任务队列。
- 第10秒时,定时器第二次到期,浏览器检查任务队列,发现之前推入的回调还在队列里(因为主线程还在while循环,没机会执行),所以不会再推入第二个相同的回调。
- while循环结束,同步执行
console.log("End"),输出End。 - 主线程现在空闲,开始处理任务队列里的回调,执行那个等待的
setInterval回调,输出setInterval。 - 这次回调执行完成后,浏览器会重新计算下一次定时器的触发时间(从这次回调结束的时间开始算5秒),所以5秒后会再次触发回调,输出
setInterval。
这就是为什么实际输出里,End之后只会先出现一次setInterval,而不是你预期的两次。
内容的提问来源于stack exchange,提问作者Avnish Ranwa
相关产品推荐
相关产品推荐

