了解Event Loop(事件循环)机制

作为前端面试八股文中最重要的一个知识点,每次被问到时总是不知从哪里说起,说的也不够完整,整理众多资料后记下笔记。

为什么会有事件循环(Event Loop)机制

大家都知道JavaScript是单线程的脚本语言,在同一时间,只能做同一件事,为了协调事件、用户交互、脚本、UI渲染和网络处理等行为,防止主线程阻塞,Event Loop方案应运而生…

JavaScript为什么是单线程的

JavaScript的主要用途是与用户互动,以及操作DOM。如果它是多线程的话会有很多复杂的问题要处理,比如有两个线程同时操作DOM,一个线程删除了当前的DOM节点,一个线程是要操作当前的DOM阶段,最后以哪个线程的操作为准?为了避免这种,所以JavaScript是单线程的。

事件循环的定义

在执行代码过程中,如果遇到一些异步代码(比如setTimeout,ajax,promise以及用户点击等操作),那么浏览器就会将这些代码放到另一个线程(在这里我们叫做幕后线程)中去执行,在前端由浏览器底层执行,在 node 端由 libuv 执行,这个线程的执行不会阻塞主线程的执行,主线程继续执行栈中剩余的代码。
当幕后线程(background thread)里的代码执行完成后(比如setTimeout时间到了,ajax请求得到响应),该线程就会将它的回调函数放到任务队列(又称作事件队列、消息队列)中等待执行。而当主线程执行完栈中的所有代码后,它就会检查任务队列是否有任务要执行,如果有任务要执行的话,那么就将该任务放到执行栈中执行。如果当前任务队列为空的话,它就会一直循环等待任务到来。这就是事件循环。

由上文任务队列引申出的其他概念

接上文,如果任务队列中,有很多个任务的话,那么要先执行哪一个任务呢?
其实js是有两个任务队列的,一个叫做 Macrotask Queue宏任务, 一个叫做 Microtask Queue微任务


事件循环执行流程

在同步代码执行完成后,才会回去检查是否有异步任务完成,并执行对应的回调,而微任务又会在宏任务之前执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 以一个经典的面试题举例,提前公布答案,输出为:1,2,3,4
// new Promise在实例化的过程中所执行的代码都是同步进行的,而then中注册的回调才是异步执行的。

setTimeout(() => {
console.log(4)
}, 0)

new Promise(resolve => {
resolve()
console.log(1)
}).then(_ => {
console.log(3)
})

console.log(2)

// 代码解析,+部分表示同步执行的代码,微任务是先于宏任务执行的
+setTimeout(_ => {
- console.log(4)
+})

+new Promise(resolve => {
+ resolve()
+ console.log(1)
+}).then(_ => {
- console.log(3)
+})

+console.log(2)

那些常见的宏任务和微任务

宏任务

ps:√表示为当前环境的api,✖表示非当前环境的api

名称 浏览器 Node
I/O
setTimeout
setInterval
setImmediate
requestAnimationFrame

微任务

名称 浏览器 Node
process.nextTick(vue中的nextTick也是微任务)
MutationObserver
Promise.then catch finally

常见的面试题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 输出依然为:1,2,3,4
// 解析:async函数在await之前的代码都是同步执行的,可以理解为await之前的代码属于new Promise实例化时传入的同步代码,await之后的所有代码都是在Promise.then中的回调

setTimeout(_ => console.log(4))

async function main() {
console.log(1)
await Promise.resolve()
console.log(3)
}

main()

console.log(2)

参考资料:
面试一定会问到的-js事件循环
详解JavaScript中的Event Loop(事件循环)机制
js事件循环
事件循环:微任务和宏任务
面试题:说说事件循环机制(满分答案来了)
微任务、宏任务与Event-Loop


了解Event Loop(事件循环)机制
https://xypecho.github.io/2021/03/11/了解Event-Loop-事件循环-机制/
作者
很青的青蛙
发布于
2021年3月11日
许可协议