我刚刚阅读Promises/A+规范,偶然发现了微任务和宏任务这两个术语:请http://promisesaplus.com/#notes
我以前从未听说过这些术语,现在我很好奇它们之间的区别是什么?
我已经试着在网上找到一些信息,但我所找到的只是www.example.com档案中的这篇文章w3.org(这并不能向我解释两者的区别):http://lists.w3.org/Archives/Public/public-nextweb/2013Jul/0018.html
此外,我还发现了一个名为“macrotask”的npm模块:https://www.npmjs.org/package/macrotask同样,没有明确区别到底是什么。
我所知道的是,它与事件循环有关,如www.example.com和www.example.com中所述https://html.spec.whatwg.org/multipage/webappapis.html#task-queuehttps://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint
我知道理论上我应该能够自己提取差异,给出这个WHATWG规范。但我相信其他人也可以受益于Maven给出的简短解释。
6条答案
按热度按时间bkhjykvo1#
事件循环的一次循环将从宏任务队列中处理一个任务(该队列在WHATWG规范中简称为 * 任务队列 *)。在该宏任务完成之后,所有可用的微任务将被处理,即在相同的复飞周期内。当这些微任务被处理时,它们可以将甚至更多的微任务排队,这些微任务都将一个接一个地运行,直到微任务队列被耗尽。
这样做的实际后果是什么?
如果一个微任务递归地将其他微任务排队,可能需要很长时间才能处理下一个宏任务。这意味着,你可能会以一个被阻塞的UI结束,或者一些完成的I/O在你的应用程序中空闲。
然而,至少关于Node.js的process.nextTick函数(它将微任务排队),存在通过process. maxTickDepth防止这种阻塞的内置保护。该值被设置为默认值1000,在达到允许处理下一个macrotask的限制后,减少了对微任务的进一步处理)
那么,何时使用什么呢?
基本上,当你需要以同步的方式异步地做一些事情时,使用微任务(例如,当你说 * 在最近的将来执行这个(微)任务 * 时)。否则,坚持使用宏任务。
示例
宏任务:setTimeout,setInterval,setImmediate,requestAnimationFrame,I/O,用户界面呈现
微任务:process.nextTick、Promises、queueMicrotask、MutationObserver
zzzyeukh2#
规范中的基本概念:
事件循环流程模型如下:
当call stack为空时,执行以下步骤-
1.选择任务队列中最早的任务(任务A)
1.如果任务A为空(意味着任务队列为空),则跳至步骤6
1.将“当前运行任务”设置为“任务A”
1.运行“任务A”(表示运行回调函数)
1.将“当前运行任务”设置为空,删除“任务A”
简化工艺模型如下:
1.运行macrotask队列中最早的任务,然后将其删除。
1.运行微任务队列中所有可用任务,然后删除它们。
1.下一轮:运行宏任务队列中下一个任务(跳转步骤2)
要记住的事项:
plicqrtu3#
我认为我们不能把事件循环从堆栈中分离出来讨论,所以:
JS有三个“堆栈”:
事件循环的工作方式如下:
如果微堆栈不为空,则不会触及微堆栈。如果微堆栈不为空或不需要任何执行,则不会触及宏堆栈。
总而言之:微任务队列几乎与宏任务队列相同,但这些任务**(进程.nextTick,承诺,对象.观察,突变观察者)**具有比宏任务更高的优先级。
微观与宏观类似,但具有更高的优先级。
在这里,你拥有了理解一切的“终极”代码。
pengsaosao4#
宏任务包括键盘事件、鼠标事件、定时器事件(setTimeout)、网络事件、Html解析、更改Urletc。宏任务代表一些离散的独立工作。微任务队列具有较高的优先级,因此宏任务将等待所有微任务首先执行。
微任务是更新应用程序状态的较小任务,应该在浏览器继续其他任务(如重新呈现UI)之前执行。微任务包括承诺回调和DOM突变更改。微任务使我们能够在重新呈现UI之前执行某些操作,从而避免不必要的UI呈现(可能显示不一致的应用程序状态)。
宏和微任务的分离使得事件循环能够区分任务类型的优先级;例如,优先考虑对性能敏感的任务。
在单循环迭代中,最多处理一个宏任务(其他任务留在队列中等待),而处理所有微任务。
浏览器通常会尝试每秒渲染页面60次,一般认为每秒60帧是动画显示流畅的速率。如果我们希望实现应用程序的流畅运行,则单个任务以及该任务生成的所有微任务应在理想情况下在16 ms内完成。如果任务执行时间超过几秒,浏览器将显示“无响应脚本”消息。
reference John Resig-secrets of JS Ninja
1cosmwyk5#
JavaScript是高级、单线程语言、解释语言。这意味着它需要一个解释器,将JS代码转换为机器代码。解释器意味着引擎。Chrome的V8引擎和Safari的webkit。每个引擎都包含内存、调用堆栈、事件循环、计时器、Web API、事件等。
事件循环:微任务和宏任务
事件循环的概念非常简单,它是一个无限循环,JavaScript引擎等待任务,执行它们,然后休眠,等待更多的任务
设置任务--引擎处理它们--然后等待更多任务(同时处于睡眠状态,CPU消耗接近于零)。可能会发生这样的情况:任务在引擎忙碌时到来,然后将其入队。任务形成一个队列,即所谓的“macrotask queue”
微任务完全来自我们的代码。它们通常由承诺创建:执行.then/catch/finally处理程序就变成了一个微任务。微任务也在await的“掩护”下使用,因为它是另一种形式的promise处理。在每个宏任务之后,引擎立即执行微任务队列中的所有任务,然后再运行任何其他宏任务或渲染或其他任何操作
vxf3dgd46#
我创建了一个事件循环伪代码,遵循4个概念:
1.setTimeout、setInterval、setImmediate、requestAnimationFrame、I/O、UI呈现是宏任务队列的一部分。将首先处理一个宏任务项。
1.process.nextTick、Promises、Object.observe、MutationObserver是微任务队列的一部分。事件循环将处理该队列中的所有项目,包括在当前迭代期间处理过的一次项目。
1.还有另一个队列称为动画队列,它保存了下一个要处理的动画更改任务项。此队列中存在的所有任务都将被处理(不包括在当前迭代中添加的新任务)。如果到了渲染时间,它将被调用
1.渲染管道将尝试每秒渲染60次(每16毫秒)