【超详细】面试中问到事件循环(Event Loop)机制?
事件循环机制
- 1. 进程与线程
- 2. 事件循环机制
- 3. 事件循环机制的执行步骤
- 4. 图解执行顺序
1. 进程与线程
1.进程
- 定义:进程是操作系统分配资源(如内存、CPU)的基本单位,每个进程独立运行且用于独立的内存
- 前端场景:浏览器中最上方每个标签页通常都对应一个独立的渲染进程,负责处理网页内容的进程(解析HTML【转换为DOM树】、CSS【处理样式表】、执行js、渲染页面【将DOM和CSS结合生成渲染树】)
- 特点:
(1) 稳定性【一个标签页的崩溃,不会影响其他标签页或浏览器主进程】
(2) 安全性:进程之间隔离
(3) 性能:多进程能充分利用CPU,并行处理多个页面渲染任务
(4) 沙盒化:渲染进程运行在沙盒(Sandbox)中,限制对系统资源直接访问,增强安全性
沙盒是一种安全机制,用于隔离运行环境,限制程序或代码的访问权限,防止对系统或其他程序造成破坏。
- 线程
- 定义:线程是进程内的执行单位,共享进程的资源,是CPU调度的最小单位。
- 前端场景:渲染进程包含多个协作进程,如JS引擎线程、GUI渲染线程等,共同完成页面交互和渲染。
JS引擎线程:处理页面在的所有逻辑(js代码)。
- 是单线程,同一时间只能执行一个任务,因此长时间运行的JS代码会阻塞页面渲染
- 与渲染线程互斥:当JS引擎线程执行时,GUI渲染线程会被挂起
- JS是单线程模型,通过事件循环机制处理异步操作,避免主线程阻塞
GUI渲染线程:
- 构建DOM树和CSSOM树,合并为渲染树;计算元素位置、大小最终将像素输出到屏幕
- 重绘与回流:当页面样式或结构发生变化则触发重新渲染。
2. 事件循环机制
是浏览器V8引擎按照先执行同步代码、再执行异步代码,如此反复执行的一种策略。
V8:是 JavaScript 的高性能执行引擎,广泛应用于 Chrome 和 Node.js
将js代码转换为机器码(CPU能直接执行的指令),大幅度提升运行速度
核心优化:(JIT )即时编译、隐藏类、内联缓存、高效 垃圾回收(GC)
3. 事件循环机制的执行步骤
在这之前需要理解宏任务和微任务
:
- 宏任务:是指由JavaScript主线程执行的任务,它包括但不限于以下情况:
- 浏览器事件(如click、mouseover等)
- 定时器任务(setTimeout、setInterval)
- 页面渲染(如回流/重绘)
- 网络请求(如fetch/XHMLHttpRequest)
(涉及I/O操作,需要异步等待,所以是宏任务,then是微任务,请求完成后触发)
宏任务通常独立于当前任务,并按顺序排队执行。先执行当前宏任务中的同步代码,再处理微任务,最后按队列顺序取下一个宏任务
- 微任务:是指由JavaScript引擎执行的任务,在宏任务之后执行,但在下一次渲染之前执行。微任务通常是由宏任务中的某个特定任务触发的,并立即执行。常见的微任务:
- Promise.then回调函数
- Async/await函数
- nextTick()
✅ 异步操作分两类:
宏任务异步(如setTimeout):放入任务队列,等待下次事件循环
微任务异步(如Promise.then):放入微任务队列,当前宏任务结束后立即执行
(即当前宏任务结束,立即清空微任务队列)
实例:
console.log("1");
setTimeout(()=>{console.log("2");Promise.resolve().then(()=>console.log("3"));
});
Promise.resolve().then(()=>console.log("4"));
console.log("5");
解释:
- 在当前第一个宏任务中,先执行其中同步任务:打印
1
和5
- 第一个宏任务中使用
setTimeout
创建一个回调函数,将其添加到宏任务队列中等待执行。 Promise.resolve().then(()=>console.log("4"));
中回调函数首先会被添加到微任务队列中。在第一个宏任务执行结束后,立即执行微任务队列中的回调函数:打印4
- 开始执行第二个宏任务(宏任务队列中取出),打印:
2
- 然后第二个宏任务中的Promise回调函数
()=>console.log("3")
会被添加到微队列当中等待执行 - 本轮事件循环结束执行微队列任务,打印
3
4. 图解执行顺序
由此形成事件循环