JavaScript中为什么setInterval无法阻止setTimeout运行?
核心原理:JavaScript事件循环机制
你对JS单线程的认知存在偏差,setTimeout和setInterval本身不会持续占用主线程,先看你运行的测试代码:
var a=true; let c=0; setTimeout(()=>{ console.log("a is false"); },2000); setInterval(()=>{ console.log(c++); },200)
- JS的单线程指的是JS代码执行栈只有一个,所有同步代码按顺序在执行栈中运行,遇到异步API时不会原地等待结果,而是把异步逻辑交给运行时提供的Web API线程(比如定时器线程、HTTP请求线程)处理,主线程继续执行后续同步代码,不会被阻塞。
- 上述代码里注册
setTimeout、setInterval的动作本身是同步任务,执行耗时极短,执行完成后主线程就处于空闲状态,根本不存在“setInterval持续占用主线程”的情况。 - 负责计时的Web API线程独立于JS主线程运行:
setInterval每间隔200ms就把打印c的回调推入宏任务队列,setTimeout在2秒到达时把自己的回调也推入宏任务队列。 - 主线程只要检测到执行栈为空,就会按照入队顺序从宏任务队列中取任务放到执行栈中执行,每个回调执行时才会短暂占用主线程,执行完成后立刻出栈释放线程,等待下一个任务。
你观察到的现象本质是:每个
setInterval的回调只有一句console.log(c++),执行耗时不到1毫秒,执行完马上释放主线程。2秒时setTimeout的回调入队,只需要等当前正在执行的interval回调运行结束,就会被调度执行,完全符合事件循环的调度逻辑。
只有同步写的死循环(比如while(true){}这类永远不会执行结束的同步代码)才会一直霸占执行栈,导致所有排队的异步回调永远没有机会执行,这才是真正的线程阻塞。
内容的提问来源于stack exchange,提问作者Vatsal A Mehta
相关产品推荐
相关产品推荐

