JS中EventLoop、宏任务与微任务的个人理解 (2)

process.nextTick(Node.js)在当前"执行栈"的尾部----下一次Event Loop(主线程读取"任务队列")之前----触发回调函数。也就是说,它指定的任务总是发生在所有异步任务之前

  紧接着第一节里说的EventLoop,当时没有考虑什么宏任务微任务,现在再加入微任务的概念再来考虑整个流程:

依旧是在调用栈和任务队列中轮询。(此时的任务队列指的是宏任务队列)

调用栈为空后,优先检查微任务队列,如果微任务队列中存在事件,则加入到调用栈中进行执行(为什么先询问的是微任务队列而不是宏任务队列,在后面解释)

注:如果在执行微任务队列中的函数时,产生了新的微任务(比如then函数嵌套),则会继续在本次执行中执行(就是说如果期间一直有微任务产生,那就会永远卡在微任务队列执行)

如果微任务队列为空,那就取宏任务队列中的事件加入到调用栈中进行执行

若在执行宏任务的时候,产生了新的微任务,就会将该微任务加入到微任务队列,该微任务队列将会在下一次宏任务执行之前执行,如图2-2。

循环。

  依旧是:两个任务队列(宏、微)只有有任务,那么主进程的调用栈就会调过去执行,没有任务的话,主进程就一直等着,直到又有任务。

JS中EventLoop、宏任务与微任务的个人理解

图 2-2 宏任务与微任务的执行顺序

  注意的是,图2-2看起来是宏任务先执行,微任务后执行,这仅仅是宏任务与微任务的先后次序,但不代表宏任务优先级比微任务高。事实是微任务的优先级是高于宏任务的。因为微任务其实是产生于宏任务的,不可能凭空产生微任务,也就不可能一开始就出现几个微任务。在本次宏任务产生微任务后,将会在下次宏任务执行之前,优先执行这些微任务。自然也就映证了设计微任务的初衷:为了让某些任务尽快执行。

  总结完整的EventLoop流程:

执行一个宏任务(调用栈中没有就从宏、微任务队列中获取)

执行过程中如果遇到微任务,就将它添加到微任务的任务队列中

宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)

当前微任务执行完毕,开始检查渲染,然后GUI线程接管渲染

渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)

  微任务在本次宏任务之后执行,在本次渲染之前执行,在下次宏任务之前执行。(宏任务 -> 微任务 -> 渲染 -> 宏任务)

 包含宏任务、微任务的异步代码分析:

// 知乎作者:Miku // 链接:https://zhuanlan.zhihu.com/p/257069622
// 注意:代码中的process.netxTick 函数存在于Node.js中
console.log('1'); setTimeout(function() { console.log('2'); process.nextTick(function() { console.log('3'); }) new Promise(function(resolve) { console.log('4'); resolve(); }).then(function() { console.log('5'); }); }); process.nextTick(function() { console.log('6'); }); new Promise(function(resolve) { console.log('7'); resolve(); }).then(function() { console.log('8'); }); setTimeout(function() { console.log('9'); process.nextTick(function() { console.log('10'); }); new Promise(function(resolve) { console.log('11'); resolve(); }).then(function() { console.log('12'); }); });

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzyfyy.html