eventLoop
Event Loop题目解析
首先根据一次弄懂Event Loop我们知道chrome73以前版本与后面版本,以及nodejs对eventLoop的表现行为是有区别的。我们这里仅仅讨论 >=chrome73的情况
在chrome中测试下面的用例时,函数的返回值,不算在输出中
题目
1 | async function a1 () { |
这道写输出结果的题目关键点在于setTimeout, async/await, Promise/Promise.resolve, then
题目解析
首先我们要知道微任务与宏任务的概念。
任务分类
宏任务包括:script全部代码、setTimeout、setInterval、setImmediate(浏览器暂时不支持,只有IE10支持,具体可见MDN)、I/O、UI Rendering。
微任务包括:Process.nextTick(Node独有)、Promise、Object.observe(废弃)、MutationObserver
执行顺序
同步任务执行完后,检查微任务队列是否为空,如果不为空,就将微任务队列以先进先出的顺序全部执行并出队。如果为空就检查宏任务队列,如果不为空,就执行一个宏任务并出队,然后再次检查微任务队列(重复上文微任务检查执行方式),如此循环。
关键点分析
Promise/then
1 | let pro = new Promise((resolve) => { |
- 首先执行同步任务,输出pro1
- 此时同步任务执行完毕,检查微任务队列不为空,所以执行微任务队列输出pro
setTimeout, Promise/then
1 | setTimeout(() => { |
- 首先执行同步任务输出normal
- 此时同步任务执行完毕,检查微任务队列不为空,所以执行微任务队列输出resolve
- 微任务队列为空,检查宏任务队列不为空,执行宏任务输出setTimeout
Promise, async/await
1 | async function a() { |
因为async/await 是Promise的语法糖,所以先把代码简化
1 | function a() { |
在async函数中使用await,相当与将await下面的代码放在then中。
await fun(), fun放在new Promise(resolve => { …这里 })
题目解答
- 首先执行同步任务输出:
script start -> a1 start -> a2 -> promise2 -> script end
- 接下来查看微任务队列, 发现不为空,然后顺序执行微任务队列。输出:
promise1 -> a1 end -> promise2.then
- 由于在执行微任务队列的最后一个任务时,又向微任务队列中增加了一个任务,所以执行完最后一个微任务后,微任务队列不为空,继续按顺序执行。输出
promise3
- 微任务队列为空,查看宏任务队列不为空,按顺序执行一个宏任务,输出
setTimeout -> a3
- 一个宏任务执行完,同时又向微任务队列增加了一个任务,此时微任务队列不为空,所以按顺序将微任务队列的任务执行完,输出
a3-end
- 微任务队列执行完,检查宏任务队列不为空,再继续执行一个宏任务,输出
second setTimeout