浏览器端
什么是event loop
我认为这是js单线程的一种事件调度机制,保证代码能够有序运行。 浏览器环境下,只需要知道调用堆栈call stack,一个宏任务队列,一个微任务队列即可。
执行规则如下:
- shift第一个宏任务(也就是当前script上下文)
let temp = 宏队列.length && 宏队列.shift()
- 将其压入栈中,并执行(包括声明函数,声明promise,赋值,运算等同步操作)
if(temp) stack.exe(temp)
- 堆栈执行完为空,检查微任务队列并执行,
while(微队列.length){
let temp = 微队列.shift()
stack.exe(temp)
}
- 当微任务队列为空,重复第一步,此时就成了一个loop
- stack.exe()期间,可能会执行
宏队列.push()
微队列.push()
event loop中的Promise
- 浏览器环境下
promise回调函数
属于微任务 - new Promise里的构造函数是同步执行的
- then回调函数理解为注册在其promise内部
- then回调函数只有在promise被决议后,才会推入微任务队列的末尾
then(xxx).then(xxx)
第一个then回调函数在堆栈中执行完毕后,返回一个新的promise,值为第一个then函数的返回值(可能是同步值,可能是promise)- 如果第一个then返回值是promise,那第二个then函数何时被推入队列末尾,取决于这个 promise何时解决
- 如果是非promise,那这个promise相当于Promise.resolve(),那这个then回调函数会立即推入到微任务队列末尾
new Promise((resolve,reject)=>{
console.log('同步执行')
resolve(1)//将当前promise的状态设为fulfilled,值设为1(等待then函数使用)
}).then()
//遇到then函数,首先判断promise的状态是否解决,
//如果解决,将 then里的回调函数添加到微任务队列的末尾
//如果没有解决,只是注册,当状态从pending变更为解决时,再将此回调函数添加到微任务队列的末尾
真题
setTimeout(
()=>{console.log(0)}// push一个宏任务
)
new Promise((resolve,reject)=>{
console.log(1)
resolve()
}).then(
/*P1.then start*/
()=>{
console.log(2)
new Promise((resolve,reject)=>{
console.log(3)
resolve()
}).then(
()=>{console.log(4)}// P3.then
).then(
()=>{console.log(5)}// P3.then.then
)
}
/*P1.then end*/
).then(
()=>{console.log(6)}// P1.then.then
)
new Promise((resolve,reject)=>{
console.log(7)
resolve()
}).then(
()=>{console.log(8)}// P2.then
)
解答:
-
第一个宏任务:
- 执行setTimeout函数,
宏任务.push(()=>{console.log(0)})
new Promise
执行构造器函数,console.log(1)- resolve()
微任务.push(P1.then)
- P1.then.then注册到P1.then上,等待执行
- 又一个
new Promise
执行构造器函数,console.log(7) - resolve()
微任务.push(()=>{console.log(8)})
- 执行setTimeout函数,
-
第一个宏任务执行完毕,检查微任务队列
[ P1.then , ()=>{console.log(8)} ]
- 执行第一个微任务P1.then函数,console.log(2)
new Promise
执行构造器函数,console.log(3)- resolve()
微任务.push(P3.then)
- P3.then.then注册在P3.then()上,等待执行
- P1.then执行完毕,返回undefined,则
微任务.push(P1.then.then)
- 此时微任务队列
[ ()=>{console.log(8)} , P3.then , P1.then.then ]
- 执行第一个微任务,console.log(8)
- 执行P3.then函数,console.log(4)
- P3.then函数执行完毕,返回值为undefined,
微任务.push(P3.then.then)
- 此时微任务队列
[ P1.then.then , P3.then.then ]
- 执行 P1.then.then函数 console.log(6)
- 执行 P3.then.then函数 console.log(5)
-
微任务队列为空,开启下一轮loop
- 宏任务队列首个宏任务压入堆栈执行,console.log(0)
结果
172384650
题目拓展
new Promise((resolve,reject)=>{
console.log(1)
resolve()
}).then(()=>{
console.log(2)
return new Promise((resolve,reject)=>{
console.log(3)
resolve()
}).then(()=>{
console.log(4)
}).then(()=>{
console.log(5)}
)
}).then(()=>{
console.log(6)
})