首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >事件循环上下文中的微任务和宏任务的区别

事件循环上下文中的微任务和宏任务的区别
EN

Stack Overflow用户
提问于 2014-09-18 14:36:24
回答 4查看 86.9K关注 0票数 239

我刚刚读完了承诺/A+规范,无意中发现了微任务和宏任务的术语:参见http://promisesaplus.com/#notes

我以前从未听说过这些术语,现在我想知道这两者有什么区别?

我已经尝试在网络上找到一些信息,但我发现的只有w3.org档案中的这篇文章(这并没有向我解释这种区别):http://lists.w3.org/Archives/Public/public-nextweb/2013Jul/0018.html

此外,我还发现了一个名为“宏任务”的npm模块:https://www.npmjs.org/package/macrotask,它没有明确区别到底是什么。

我所知道的是,它与事件循环有关,如https://html.spec.whatwg.org/multipage/webappapis.html#task-queuehttps://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint所述。

考虑到WHATWG规范,我知道理论上我应该能够自己提取差异。但我相信其他人也可以从专家的简短解释中获益。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-09-19 12:29:56

事件循环的一次遍历将使从宏任务队列中处理一个任务(这个队列在WHATWG规范中被简单地称为任务队列)。在此宏任务完成后,所有可用的微任务将被处理,即在相同的执行周期内。当这些微任务被处理时,它们可以对更多的微任务排队,所有这些任务都将一个一个地运行,直到微任务队列耗尽为止。

这样做的实际后果是什么?

如果微任务递归地排队其他微任务,则可能需要很长时间才能处理下一个宏任务。这意味着,您可能以阻塞的UI结束,或者在应用程序中完成一些I/O空闲。

但是,至少关于Node.js的process.nextTick函数(它将微任务排队),可以通过process.maxTickDepth对这种阻塞进行内置的保护。此值设置为默认值1000,在达到此限制后,将减少对微任务的进一步处理,从而允许处理下一个宏任务)

那什么时候用什么?

基本上,当您需要以同步方式异步完成事情时,使用微任务(也就是说,当您在最近的将来执行这个(微)任务时)。否则,坚持宏任务

示例

宏任务: setTimeoutsetIntervalsetImmediaterequestAnimationFrameI/O、UI呈现

微任务: process.nextTick应许queueMicrotaskMutationObserver

票数 344
EN

Stack Overflow用户

发布于 2015-06-18 08:22:24

等级库中的基本概念

  • 事件循环有一个或多个任务队列。(任务队列是宏任务队列)
  • 每个事件循环都有一个微任务队列。
  • 任务队列=宏任务队列!=微任务队列
  • 可以将任务推入宏任务队列或微任务队列。
  • 当任务被推入队列(微/宏)时,我们的意思是准备工作已经完成,所以现在就可以执行任务了。

事件循环过程模型如下:

调用堆栈为空时,执行步骤-

  1. 在任务队列中选择最老的任务(任务A)
  2. 如果任务A为空(意味着任务队列为空),跳到步骤6
  3. 将“当前正在运行的任务”设置为“任务A”
  4. 运行“任务A”(意思是运行回调函数)
  5. 将“当前正在运行的任务”设置为空,删除“任务A”
  6. 执行微任务队列
    • (a).select微任务队列中最古老的任务(任务x)
    • (b).if任务x为空(意味着微任务队列为空),跳到步骤(g)
    • (c).set“当前正在运行的任务”到“任务x”
    • (d).run“任务x”
    • (e).set“当前正在运行的任务”为空,删除“任务x”
    • (f).select微任务队列中的下一个最老任务,跳到步骤(B)
    • (g).finish微任务队列;

  1. 跳到第一步。

简化的过程模型如下:

  1. 运行宏任务队列中最老的任务,然后删除它。
  2. 运行微任务队列中的所有可用任务,然后删除它们。
  3. 下一轮:在宏任务队列中运行下一个任务(跳转步骤2)

要记住的事情:

  1. 当任务(在宏任务队列中)正在运行时,新事件可能是registered.So,新任务可能是created.Below,这是两个新创建的任务:
    • PromiseA.then()的回调是一个任务
      • promiseA被解析/拒绝:任务将被推入当前一轮事件循环中的微任务队列中。
      • promiseA挂起:任务将在下一轮事件循环中被推入微任务队列(可能是下一轮)

代码语言:javascript
复制
- setTimeout(callback,n)'s callback is a task,and will be pushed into macrotask queue,even n is 0;

  1. 微任务队列中的任务将在当前一轮中运行,而宏任务队列中的任务必须等待下一轮事件循环。
  2. 我们都知道回调“点击”,“滚动”,“阿贾克斯”,“setTimeout”.是任务,但是我们也应该记住js代码作为一个整体在脚本标记中也是一个任务(一个宏任务)。
票数 136
EN

Stack Overflow用户

发布于 2022-01-27 17:38:16

宏任务包括键盘事件、鼠标事件、计时器事件(setTimeout)、网络事件、Html解析、更改Urletc。宏任务表示一些独立的独立工作。微任务队列具有较高的优先级,因此宏任务将等待所有微任务的执行。

微任务是更新应用程序状态的较小任务,应该在浏览器继续执行其他任务之前执行,例如重新呈现UI。微任务包括承诺回调和DOM突变更改。微任务使我们能够在UI重新呈现之前执行某些操作,从而避免出现可能显示不一致的应用程序状态的不必要的UI呈现。

宏任务和微任务的分离使事件循环能够对任务类型进行排序;例如,优先处理性能敏感的任务。

在单循环迭代中,最多只处理一个宏任务(其他任务在队列中等待),而所有的微任务都被处理。

  • 两个任务队列都放在事件循环之外,以指示将任务添加到其匹配队列的行为发生在事件循环之外。否则,在执行JavaScript代码时发生的任何事件都将被忽略。检测和添加任务的行为与事件循环分别执行。
  • 两种类型的任务一次只执行一次。当一个任务开始执行时,它被执行到完成。只有浏览器才能停止任务的执行;例如,如果任务占用了太多的时间或内存。
  • 所有微任务都应该在下一次呈现之前执行,因为它们的目标是在呈现发生之前更新应用程序状态。

浏览器通常尝试以每秒60次的速度呈现页面,人们认为每秒60帧是动画呈现平滑的速度。如果我们想要实现顺利运行的应用程序,一个单一的任务,以及所有由该任务生成的微任务应该在理想的16毫秒内完成。如果任务执行时间超过几秒钟,浏览器将显示一条“响应迟钝的脚本”消息。

参考John Resig- JS忍者的秘密

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25915634

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档