资讯专栏INFORMATION COLUMN

浅析 JS 事件循环之 Microtask 和 Macrotask

sihai / 738人阅读

摘要:常见应用则是为了完成一些更新应用程序状态的较小的任务,如处理的回调和的修改,以便让这些任务在浏览器重新渲染之前执行。常见应用执行顺序的实现需要至少一个和至少一个。

简介

我们在上一篇 《浅析 JS 中的EventLoop 事件循环》 中提到一个 Event Queue,其实在事件循环中 queue 一共有两种,还有一种叫 Job Queue

其中

Event Queue 在 HTML 规范中被称为 Task Queue,但是为了区分,一般都叫作 Macrotask Queue
Job Queue 是在 ECMAScript 规范中谈及处理 Promise 回调时提到的,但是由于和 V8 中的实现比较相似,所以一般都称为 Microtask Queue
Macrotask

Macrotasks 包含了解析 HTML、生成 DOM、执行主线程 JS 代码和其他事件如 页面加载、输入、网络事件、定时器事件等。从浏览器的角度,Macrotask 代表的是一些离散的独立的工作。

常见应用
setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI rendering

Microtask

Microtasks 则是为了完成一些更新应用程序状态的较小的任务,如处理 Promise 的回调和 DOM 的修改,以便让这些任务在浏览器重新渲染之前执行。Microtask 应该以异步的方式尽快执行,所以它们的开销比 Macrotask 要小,并且可以使我们在 UI 重新渲染之前执行,避免了不必要的 UI 渲染。

常见应用
process.nextTick, Promises, Object.observe, MutationObserver

执行顺序

Event Loop 的实现需要至少一个 Macrotask Queue 和至少一个 Microtask Queue。为了便于理解,我们都简化成一个。
简单来说,Microtask Queue 具有更高的优先级,即执行一个 Macrotask 任务后,就会清空整个 Microtask Queue,此时如果有新的 Microtask 加入也会被执行。

所以我们来看下面的代码:

执行顺序是什么?
我们已经知道 setTimeout 是 Macrotask,Promise 是 Microtask,而这段代码从上到下执行也是一个 Macrotask

步骤:

开始执行,执行脚本作为一个任务进入 Macrotask Queue,同时进入调用栈执行

Line 1, 输出 script start

Line 3 的 setTimeout 回调进入 Macrotask Queue 等待

Line 7 的回调进入 Microtask Queue 等待

Line 13 输出 script end,此时脚本执行完成(即完成了一个 Macrotask)

开始执行 Microtask Queue,从中拿出一个放入调用栈执行

开始执行 Line 7 的回调,该回调输出 promise1,返回 undefined

Line 9 的回调进入 Microtask Queue,由于 Microtask Queue 没有清空,直接执行该回调,输出 promise2,该回调返回 undefined

Microtask Queue 已清空(此时浏览器可以更新渲染UI),开始将 Macrotask Queue 中任务放入调用栈执行

执行 Line 3 的回调,输出 setTimeout,Macrotask Queue 清空

程序执行完成

所以打印顺序为:

script start -> script end -> promise1 -> promise2 -> setTimeout

PS. 上面的这段代码执行流程,建议看原文的倒数第二篇参考文章,有动态交互操作可以演练。

总结

Microtask 相比 Macrotask 具有更高的优先级

Macrotask 总是在 JS 代码执行完成并且 Microtask Queue 清空之后执行

JS 代码执行本身也是一个 Macrotask

Microtask Queue 清空后有可能会重新渲染 UI

Promise 属于 Microtask,setTimeout 属于 Macrotask

总体的执行顺序为:常规代码 -> promises -> events 和 setTimeout 等

参考文章

原文链接
ECMA262 Job Queues
HTML Standard Task Queue
HTML系列:macrotask和microtask
microtask and macrotask a hands on approach
difference-between-microtask-and-macrotask-within-an-event-loop-context

公众号:码力全开

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/104508.html

相关文章

  • 浅析 Vue 2.6 中的 nextTick 方法

    摘要:核心的异步延迟函数,用于异步延迟调用函数优先使用原生原本支持更广,但在的中,触摸事件处理程序中触发会产生严重错误的,回调被推入队列但是队列可能不会如期执行。 浅析 Vue 2.6 中的 nextTick 方法。 事件循环 JS 的 事件循环 和 任务队列 其实是理解 nextTick 概念的关键。这个网上其实有很多优质的文章做了详细介绍,我就简单过过了。 以下内容适用于浏览器端 JS,...

    fobnn 评论0 收藏0
  • 浏览器Node不同的事件循环(Event Loop)

    摘要:浏览器中与中事件循环与执行机制不同,不可混为一谈。浏览器环境执行为单线程不考虑,所有代码皆在执行线程调用栈完成执行。参考文章强烈推荐不要混淆和浏览器中的强烈推荐中的模块强烈推荐理解事件循环一浅析定时器详解 注意 在 node 11 版本中,node 下 Event Loop 已经与浏览器趋于相同。在 node 11 版本中,node 下 Event Loop 已经与浏览器趋于相同。在 ...

    haitiancoder 评论0 收藏0
  • 理解javascript中的事件循环(Event Loop)

    摘要:主线程会暂时存储等异步操作,直接向下执行,当某个异步事件触发时,再通知主线程执行相应的回调函数,通过这种机制,避免了单线程中异步操作耗时对后续任务的影响。 背景 在研究js的异步的实现方式的时候,发现了JavaScript 中的 macrotask 和 microtask 的概念。在查阅了一番资料之后,对其中的执行机制有所了解,下面整理出来,希望可以帮助更多人。 先了解一下js的任务执...

    mykurisu 评论0 收藏0
  • 【新手向】Node.js事件循环中的:MacrotaskMicrotask

    摘要:一句话解释在事件循环机制中,有任务两个队列队列和队列。设置任务为目前运行的任务,并执行。应该是考虑到了这一点,至少任务中的任务,是被设置了在一个事件循环中的最大调用次数的,叫。参考材料理解事件循环 在Node学习过程中,不可避免的需要对事件循环机制做深入理解,其中Macrotask(大型任务)和Microtask(小型任务)比较令人困惑,在一番google之后,我发现了几篇资料能比较好...

    CoderDock 评论0 收藏0
  • 一篇文章教会你Event loop——浏览器Node

    摘要:如果没到毫秒,那么阶段就会跳过,进入阶段,先执行的回调函数。参考文档什么是浏览器的事件循环不要混淆和浏览器中的定时器详解浏览器和不同的事件循环深入理解事件循环机制篇中的执行机制 最近对Event loop比较感兴趣,所以了解了一下。但是发现整个Event loop尽管有很多篇文章,但是没有一篇可以看完就对它所有内容都了解的文章。大部分的文章都只阐述了浏览器或者Node二者之一,没有对比...

    Leck1e 评论0 收藏0

发表评论

0条评论

sihai

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<