此时当前宏任务(script 主代码块)执行完毕,并不从当前宏任务队列中读取任务。而是立马清空当前宏任务所产生的微任务队列。将两个微任务依次放入执行栈中执行。执行完毕,打印 promise1、promise2。栈空。此时,第一轮事件循环结束。
紧接着,再去读取宏任务队列中的任务,time over 被打印。栈空。
因此,宏任务和微任务的执行机制如下:
执行一个宏任务(栈中没有就从宏任务队列中获取)
执行过程中遇到微任务,就将它添加到微任务的任务队列中
宏任务执行完毕,立即执行当前微任务队列中的所有微任务(依次执行)
当前所有微任务执行完毕后,开始检查渲染,GUI 线程接管渲染
渲染完毕后,JS 引擎继续开始下一个宏任务,从宏任务队列中获取
async & await因为,async 和 await 本质上还是基于 Promise 的封装,而 Promise 是属于微任务的一种。所以使用 await 关键字与 Promise.then 效果类似:
setTimeout(_ => console.log(4)) async function main() { console.log(1) await Promise.resolve() console.log(3) } main() console.log(2) // 1 // 2 // 3 // 4async 函数在 await 之前的代码都是同步执行的,可以理解为 await 之前的代码都属于 new Promise 时传入的代码,await 之后的所有代码都是 Promise.then 中的回调,即在微任务队列中。
五、总结js 单线程实际上时解释执行 js 代码的只有一个线程,但是浏览器的渲染是多线程的。
异步和同步的概念与区别,异步任务有哪些。
栈、堆、队列的特点和使用场景。
事件队列以及事件循环机制。
es6 下,宏任务与微任务的执行过程。
参考:
微任务、宏任务与Event-Loop
JavaScript 运行机制详解:再谈Event Loop
JS事件循环
[译] 深入理解 JavaScript 事件循环(二)— task and microtask
Help, I'm stuck in an event-loop