首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Javascript显式添加微任务或宏任务

Javascript显式添加微任务或宏任务
EN

Stack Overflow用户
提问于 2016-12-10 12:51:07
回答 1查看 1.6K关注 0票数 6

从我对javascript虚拟机工作方式的全球理解中,我可以清楚地看到,微任务/宏任务的概念发挥了很大的作用。

以下是我对此的理解:

  • VM‘转向’是将一个宏任务从VM宏任务队列中取出并执行的事实。
  • 在VM转时,可以将微任务添加到当前宏任务的微任务队列中。
  • 微任务可以将其他微任务推送到当前宏任务的微任务队列中。
  • 当微任务队列为空时,VM循环将结束。

我的问题是:

为什么没有明确的API来操作这两个队列.

有点像

  • pushToMacroTask( function )
  • pushToMicroTask( function )

实际上,操纵这些队列的唯一方法是使用setTimeout()将任务添加到宏任务队列中,使用Promises将任务添加到微任务队列中。

我同意,但这并不能给我们一个有意义的API,你不认为吗?

这个概念对JS来说应该是“隐藏”的,并且只在一些讨厌的情况下使用吗?

你知道那个主题是否有W3C规范吗?

是否所有VM引擎都以相同的方式实现了这个概念?

我很高兴听到关于这方面的故事和意见。

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-12-10 14:59:25

是否有关于微/宏任务的W3C规范?

W3C谈到任务队列

当用户代理要对任务排队时,它必须将给定的任务添加到相关事件循环的任务队列之一。来自一个特定任务源的所有任务(例如定时器产生的回调、用于鼠标移动的事件、为解析器排队的任务)必须始终添加到同一个任务队列中,但是来自不同任务源的任务可能被放置在不同的任务队列中。

EcmaScript2015谈到作业队列,并要求至少支持两个:

  • ScriptJobs:验证和评估ECMAScript脚本和模块源代码文本的作业。
  • PromiseJobs:是对承诺达成协议的回应。

这个语言定义不知道可能的事件循环,但是可以想象一个或多个作业队列被保留用于W3C规范中提到的任务队列。浏览器将根据setTimeout任务队列规范(链接到作业队列)触发W3C回调,而承诺必须直接使用作业队列规范(而不是任务队列)。还提到代理可以将任务插入到作业队列中:

或者,实现可以选择等待某个特定于实现的代理或机制来排队新的PendingJob请求。

EcmaScript规范不强制为不同的作业队列提供服务的优先级:

此规范没有定义服务多个作业队列的顺序。ECMAScript实现可以将对作业队列的PendingJob记录的FIFO评估与对一个或多个其他作业队列的PendingJob记录的评估交织在一起。

因此,这里似乎没有严格的要求,在setTimeout任务之前应该为承诺的实现服务。但是,网络超文本应用技术工作组WHATWG在覆盖事件循环时更为具体

每个事件循环都有一个微任务队列。微任务是最初要在微任务队列中排队的任务,而不是任务队列。

2019年增加了,平均时间活HTML标准 WHATWG现在包括以下内容:

8.6微任务排队 Self.queueMicrotask(回调) 将微任务排队以运行给定的回调。 queueMicrotask(callback)方法必须对微任务排队以调用callback,如果callback抛出异常,则报告异常。 queueMicrotask()方法允许作者对微任务队列调度回调。这允许它们的代码在当前执行的任务运行到完成并且JavaScript执行上下文堆栈为空之后运行,但不会将控制权返回给事件循环,例如使用setTimeout(f, 0)时就是如此。

所有的VM引擎都是这样实现的吗?

历史上,不同的浏览器实现会导致不同的执行顺序。2015年的文章可能是一个有趣的读物,可以看到它们有多么不同:

有些浏览器..。正在运行承诺回调后的setTimeout。很可能,他们称承诺回调是一个新任务的一部分,而不是一个微任务。 FirefoxSafari正确地耗尽了单击侦听器之间的微任务队列,如突变回调所示,但承诺的排队方式似乎不同。..。对于边缘,我们已经看到它的队列承诺是错误的,但它也没有耗尽单击侦听器之间的微任务队列,而是在调用所有侦听器之后才这样做。

自那时以来,几个问题得到了解决和协调。

但是,请注意,不需要有一个微任务队列,也不需要一个宏任务队列。可以有几个队列,每个队列都有自己的优先级。

有意义的API

当然,实现您建议的两个功能并不困难:

代码语言:javascript
运行
复制
let pushToMicroTask = f => Promise.resolve().then(f);
let pushToMacroTask = f => setTimeout(f);

pushToMacroTask(() => console.log('Macro task runs last'));
pushToMicroTask(() => console.log('Micro task runs first'));

2019,现在我们有了queueMicrotask(),有了一个本机实现。下面是一个演示,将该方法与上面基于承诺的实现进行比较:

代码语言:javascript
运行
复制
let queuePromisetask = f => Promise.resolve().then(f);
let queueMacrotask= f => setTimeout(f);

queueMicrotask(() => console.log('Microtask 1'));
queueMacrotask(() => console.log('Macro task'));
queuePromisetask(() => console.log('Promise task'));
queueMicrotask(() => console.log('Microtask 2'));

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

https://stackoverflow.com/questions/41075724

复制
相关文章

相似问题

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