js Event loop 事件循环记录篇
js event loop 知识点
js
是单线程的- 单线程任务又分为
同步任务
和异步任务
异步任务
又分为宏任务
和微任务
js
执行过程
从<script>
标签开始,线程任务就开始按顺序进入了执行栈,
- 当遇到
同步任务
在主线程中直接被执行 - 当遇到
异步任务时
会进入异步处理模块并注册相应的回调函数,注册完成后回调函数进入任务队列 - 如果是
宏任务
会开启开启一个新的宏任务队列,如果遇到微任务
进入微任务队列
每遇到一个
宏任务
会开启一个新的宏任务队列,而微任务
队列只有一个 每次执行宏任务
之前会检查是否存在微任务
,如果存在则将微任务
队列中的所有任务执行完后再执行宏任务
常见的宏任务
:
script(全局任务)
setTimeout
setInterval
setImmediate
I/O
UI render
常见的 微任务
:
Promise.then()/catch()/finally()
process.nextTick(node.js)
MutationObserver
在 js
执行过程中,如果是同步任务,那么就会顺序执行下来,如果遇到宏任务执行函数就会开启一个新的宏任务队列,并将宏任务放入进去,如果遇到微任务执行函数,那么就会将这个函数放入到微队列中,待同步任务执行栈为空时,微任务依次进入栈中执行,每次执行宏任务之前会检查是否存在微任务,如果存在则将微任务队列中的所有任务执行完后再执行宏任务
DEMO1:
<script>
console.log(1)
setTimeout(() => {
console.log(2)
})
new Promise((resolve, reject) => {
console.log('3')
resolve()
}).then(() => {
console.log(4)
})
<script>
// 执行结果为:1 3 4 2
执行过程解析:
script
标签就是一个宏任务,顺序执行script标签里面的代码- 遇到
console.log(1)
为同步任务 则直接执行 输出1
- 遇到
setTimeout
函数为宏任务,新开启一个宏任务队列,将它放进去,先不执行,等同步任务和微任务跑完了再执行, - 遇到
promise
,promise
的函数是同步任务,所以直接输出3
,这时的结果是1 3
- 之后
promise
调用then()
,then()
是微任务,将它放入到微任务队列,等同步任务执行完之后就开始执行微任务 - 这时代码已经跑完了,没有同步任务了,这时就会去执行微队列中的微任务,微队列就只有一个
then()
,故输出4, 结果1 3 4
- 微任务没有任务了,就去执行宏队列中的宏任务setTimeout,故结果为:
1 3 4 2
DEMO2:
new Promise((resolve, reject) => {
console.log('2') // 1. 同步任务 2
resolve()
}).then(() => {
console.log('3') // 微任务
}).then(() => {
console.log('4') // 微任务 之后的 二级微任务
})
new Promise((resolve, reject) => {
resolve()
}).then(() => {
console.log('12') // 微任务
}).then(() => {
console.log('13') // 微任务 之后的 二级微任务
}).then(() => {
console.log('14') // 二级微任务 之后的 三级微任务
})
Promise.resolve().then(() => {
console.log('5') // 微任务
})
let _promise = () => new Promise((resolve, reject) => {
console.log('6') // 同步任务
resolve()
})
setTimeout(() => {
console.log('7') // 宏任务
Promise.resolve().then(() => {
console.log('8')
})
}, 100)
setTimeout(() => {
console.log('9') // 宏任务
}, 0)
_promise().then(() => {
console.log('10') // 微任务
})
console.log('11'); // 同步任务
执行结果:2 6 11 3 12 5 10 4 13 14 9 7 8
执行过程:
1、先顺序执行同步任务,得到的结果为:2 6 11
2、在执行微任务: 首先执行一级微任务,之后执行二级微任务
第一个then(),第二个then() 我们称之为第二级微任务,以此类推...
2.1、执行完一级微任务之后的结果为:`2 6 11, 3 12 5 10`
2.2、接着执行二级微任务:`2 6 11, 3 12 5 10,4 13`
2.3接着执行三级微任务:`2 6 11, 3 12 5 10,4 13,14`
3、自此微任务执行结束,接着执行新的宏任务:
setTimeout
延迟最短的先执行,故这边先执行 setTimeout
延迟为 0
的 console.log('9')
3.1 执行完第一个宏任务之后的结果为:`2 6 11, 3 12 5 10,4 13,14,9`
3.2、接着继续执行延迟为 `100` 的`setTimeout`的第二个宏任务:
执行之后的结果为:`2 6 11, 3 12 5 10,4 13,14,9, 7 8`
自此所有的函数执行完毕,得到的结果为:
- 同步代码执行之后得到:
2 6 11
- 一级微任务执行之后得到:
3 12 5 10
- 二级微任务执行之后得到:
4 13,
- 三级微任务执行之后得到:
14
- 第一个宏任务执行之后得到:
9
- 第二个宏任务执行之后得到:
7 8
总结得到的结果为:
2 6 11 3 12 5 10 4 13 14 9 7 8
.