之前一直停留在主线程先执行,异步后执行的浅理解中,后来随着不断的学习,才渐渐意识到这里面还是有点复杂的,不过我不打算写很多。一幅图来说明这个复杂的关系
processTick可理解为node中的延时器。
接下来看一道题目
// 1 7 6 8 2 4 9 11 3 10 5 12 console.log('1'); // 1 setTimeout(function() { // 2 console.log('2'); process.nextTick(function() { // 3 console.log('3'); }) new Promise(function(resolve) { // 4 console.log('4'); resolve(); }).then(function() { console.log('5') }) }) // 6 process.nextTick(function() { console.log('6'); }) // 7 8 new Promise(function(resolve) { console.log('7'); resolve(); }).then(function() { console.log('8') }) setTimeout(function() { // 9 console.log('9'); process.nextTick(function() { console.log('10'); }) new Promise(function(resolve) { // 11 console.log('11'); resolve(); }).then(function() { console.log('12') }) })
根据上述的知识,可以得出下面的分析,进而得出答案
首先宏script部分 :1 7 ,毋庸置疑,如果你说new Promise( )怎么就立即执行了,先去看看new做的四件事 执行了还不算完,还要把异步的写进事件列表,进而注册事件队列
现在宏事件队列有 : 两个setTimeout里的异步函数 还有一个process.nextTick()的微异步函数,外加一个then也有一个
执行当前所有的微任务里的任务 : 6 8
执行当前所有宏任务队列里的任务 : 首先执行第一个setTimeout里的异步 : 打印 2 ,又一个process.nextTick()微任务存到队列中(为了省事省去了到事件列表的步骤),打印4,又一个微任务then中的异步函数存到队列中
执行第二个setTimeout里的异步函数 : 打印 9,又一个process.nextTick()微任务存到队列中,打印11,又一个微任务then中的异步函数存到队列中
最后执行微任务 : 此时微任务里有两个process.nextTick()微任务,两个then微任务,所以首先把两个process.nextTick()微任务执行完再去执行两个then 结果打印 3 10 5 2
总结 : 事件循环 , 宏微交替
最后附上我学习js运行机制的地址:https://juejin.im/post/59e85eebf265da430d571f89,写的真的好,耐心看,但是在那篇博客在宏微交替的理解上有偏差,或许是因为node版本不一样了,我这是没问题的
注意:上文仅针对node环境下,浏览器环境下运行机制简单说一下:首先宏微任务的分配没有改变,但是执行的时候是抓一个宏,执行全部微任务,再去抓一个宏任务,执行所有微任务,有点差异。