继续判断微任务队列是否有回调函数可执行,由于process.nextTick的执行优先级大于promise,所以会先执行process.nextTick的回调,输出 console.log('h');、如果有多个process.nextTick的回调,会将process.nextTick的所有回调执行完成后才会去执行其它微任务的回调。
当nextTick所有的回调执行完后,执行promise的回调,输出console.log('c');,直到promise的回调队列执行完后,又会去判断是否还有微任务。
setImmediate
微任务执行完后,开始执行新的宏任务,执行setImmediate的回调,输出 console.log('g');
### 3. setImmediate
这里为什么要把 setImmediate 单独拿出来说呢,因为它属于宏任务的范畴,但又有点不一样的地方。
先看一段代码
按照我们上面的分析逻辑,我们会认为这段代码的输出结果应该是a b c d。
如果我们把使用Node 0.10.x的版本去执行这段代码,结果确实是输出a b c d
然而,在Node 大于 4.x 的版本后,在执行setImmediate的,会使用while循环,把所有的immediate回调取出来依次进行处理。
这也是我为什么把 setImmediate 比喻成 一桌子人客户的原因。
## 最后看一段代码看看自己是否真的掌握了
如果还没有掌握,欢迎评论区吐槽
<script> console.log("start"); process.nextTick(() => { console.log("a"); setImmediate(() => { console.log("d"); }); new Promise(res => res()).then(() => { console.log("e"); process.nextTick(() => { console.log("f"); }); new Promise(r => { r() }) .then(() => { console.log("g"); }); setTimeout(() => { console.log("h"); }); }); }); setImmediate(() => { console.log("b"); process.nextTick(() => { console.log("c"); }); new Promise(res => res()).then(() => { console.log("i"); }); }); console.log("end"); </script>输出的结果为: start end a e g f h b d c i
简单分析一下代码:
第一轮事件循环开始,执行script代码,输出 start end,将process.nextTick 的回调加入微任务队列中,将setImmediate的回调加入到宏任务的队列中
执行微任务队列中的process.nextTick的回调,输出 a 、将setImmediate的回调加入到宏任务的队列中,遇到promise、将回调加入到微任务队列中。
宏任务 微任务setImmediate promise.then
setImmediate -
继续执行微任务队列中的回调,取出promise.then并执行,输出e,将process.nextTick的回调放入到微任务中,遇到promise、将回调加入到微任务队列中。
判断当前promise的回调队列是否还有回调函数没执行,如果有,将继续执行,取出刚刚放入的promise的回调,输出 g,当Promise回调队列执行完后,继续判断当前是否还有微任务。
取出process.nextTick的回调并执行,输出g
宏任务 微任务setImmediate -
setImmediate -
setTimeout -
当前微任务队列为空后,开始执行宏任务,因为setTimeout的优先级大于setImmediate,所以先取出setTimeout的回调并执行,输出h
当前微任务队列还是为空,开始执行宏任务,取出所有setImmediate的回调函数,并执行,输出b d,将 process.next 与 promise的回调放入到微任务队列中。
取出微任务队列中的回调函数,并执行,输出 c i
总结Event Loop 作为面试的高频题,静下心来认真的分析一下,其实不难理解。
欢迎关注欢迎关注公众号“码上开发”,每天分享最新技术资讯