异步 JavaScript 之理解 macrotask 和 microtask

先来看一段关于promise的常见面试题,写出数字的打印顺序:
setTimeout(function() {
    console.log(4)
},
0);
new Promise(function(resolve) {
    console.log(1)
    for (var i = 0; i < 10000; i++) {
        i == 9999 && resolve()
    }
    console.log(2)
}).then(function() {
    console.log(5)
});
console.log(3);

在输出结果之前,我们先来了解两个概念 macrotasks 和 microtasks。直译过来就是大型任务和微型任务。在javascript中,这两个任务有什么不同呢?microtasks比macrotasks优先执行。

在V8引擎实现中,任务队列分为 macrotasks 和 microtasks。两个队列各包含不同的任务:

macrotasks: script(整体代码),setTimeout, setInterval, setImmediate, I/O, UI rendering

microtasks: process.nextTick, Promises, Object.observe, MutationObserver。

从列表中可以看出,上述代码中Promise中的then方法中的函数会被推入 microtasks 队列,而setTimeout的任务会被推入 macrotasks 队列。

上述代码在执行过程中遇到了setTimeout,将其回调加入到macrotask queue中, 然后,遇到了promise.then,放入到了另一个队列microtask queue。 等整个主线程执行完后, 就会从microtask queue中取出函数执行,直到microtask queue中的全部任务执行完成,才会执行macrotask queue中的函数。 因此promise.then的回调比setTimeout先执行。

在javascript中,microtask queue会优先于macrotask queue执行。microtask 就相当于头图中的VIP客户,可以随时插队,插入到第一个人和第二个人之间,第一个人相当于正在执行的主线程,而第二个人相当于macrotasks即将要执行的回调。

上面代码的运行结果为:1 2 3 5 4

本文分享自微信公众号 - nodejs全栈开发(geekclass)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-12-07

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券