讲解可看:
【事件循环】【前端】事件原理讲解
主线程会执行任务队列中的任务,并在固定的时间内(如每秒60次)进行渲染
button.addEventListener('click',()=>{
box.style.display ='none';
box.style.display = 'block';
box.style.display = 'none';
box.style.display = 'block';
box.style.display = 'none';
box.style.display = 'block';
box.style.display = 'none';
});
并不会出现反复显示隐藏的效果,只会渲染最后一次
什么是事件循环
- JS是单线程,防止代码阻塞,我们把代码(任务)分为:同步和异步
- 同步代码给js引擎执行,异步代码交给宿主环境(浏览器、Node)
- 同步代码放入执行栈中,异步代码等待时机成熟送入任务队列排队
- 执行栈执行完毕,会去任务队列看是否有异步任务,有就送到执行栈执行,反复循环查看执行,这个过程是事件循环(eventloop)
原理
执行顺序:同步=》事件循环=》微任务=》宏任务
其核心原理如下:
-
执行栈(Call Stack)
同步任务直接进入执行栈,按顺序执行。遇到异步任务时,JavaScript 会将其回调函数注册到对应的任务队列中,继续执行后续代码 -
任务队列(Task Queue) 异步任务完成后,回调函数会被放入任务队列。任务队列分为两种:
-
宏任务队列(Macrotask Queue) :包含
Script、setTimeout、setInterval、I/O 操作、DOM 事件等 -
微任务队列(Microtask Queue) :包含
Promise.then、MutationObserver、process.nextTick(Node.js)等
-
-
事件循环流程
-
执行同步代码:所有同步任务(视为第一个宏任务)在主线程依次执行。
-
处理微任务队列:检查微任务队列,依次执行所有微任务,直到队列清空(包括执行过程中新添加的微任务)。
-
执行下一个宏任务:从宏任务队列中取出一个任务执行。
-
重复步骤 2-3:形成事件循环,直至所有任务完成。
-
示例:
console.log('Start'); setTimeout(() => console.log('宏任务'), 0); Promise.resolve().then(() => console.log('微任务')); console.log('End'); // 输出顺序:Start → End → 微任务 → 宏任务
点击后输出为:Listener 1→MicroTask 1→Listener 2→MicroTask 2
点击后输出为:Listener 1→Listener 2→MicroTask 1→MicroTask 2