事件循环

事件循环

JS是单线程语言,同一时间只能执行一个任务

如果一个任务耗时过长(网络请求、文件读取),会阻塞后续代码的进行

同步任务:立刻放入JS引擎(JS主线程)执行,原地等待结果

异步任务:先放入宿主环境(浏览器/Node),不阻塞主线程,在将来执行

执行过程

过程中一共有三块环境:执行栈宿主环境任务队列

按代码上下文顺序

将同步任务压入执行栈

将异步任务压入宿主环境

在宿主环境中执行时机到来时(比如定时器到期),将宿主环境中异步任务(比如定时器)的回调函数推送给任务队列

此时执行栈会去看任务队列有没有异步任务需要执行,如果有则将异步任务推送到执行栈中执行

执行栈在同步任务执行完后会反复地去任务队列看有没有需要执行的异步任务

这个反复查找的过程就叫事件循环

宏任务/微任务

JS将 异步任务 分为宏任务和微任务

宏任务宿主 发起

script (代码块)

setTimeout / setInterval 定时器

微任务JS引擎 发起

promise (promise内部是同步,then/catch是回调异步)

Async/Await

procsee.nextTick (node)

Object.observe

执行顺序

先看执行栈(同步任务)→ 再看微任务队列(JS相关)→ 最后看宏任务队列

image-20250419103641540

执行完一个宏任务,会再次清空微任务队列然后执行下一个任务

例题

1
2
3
4
5
6
7
8
9
10
11
12
13
console.log(1)
setTimeout(() => {
console.log(2)
}, 0)
const p = new Promise((resolve, reject) => {
console.log(3)
resolve(4)
console.log(5)
})
p.then((res) => {
console.log(res)
})
console.log(6)

👆打印:135642

1
2
3
4
5
6
7
8
9
10
11
12
13
new Promise((resolve,reject)=>{
resolve(1)
console.log(2)
new Promise((resolve,reject)=>{
resolve(3)
console.log(4)
}).then(res=>{
console.log(res)
})
}).then(res=>{
console.log(res)
})
console.log(5)

👆打印:24531 (promise微任务看.then的位置而不是看resolve())