Javascript API,用于显式添加微任务或宏任务 [英] Javascript API to explicitly add micro tasks or macro tasks

查看:188
本文介绍了Javascript API,用于显式添加微任务或宏任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据我对javascript虚拟机如何工作的全球理解,我可以清楚地看到微任务/宏任务的概念发挥了重要作用。

From my global understanding of how javascript virtual machines works, i can clearly see that the concept of micro task / macro task play a big role.

以下是我对此的理解:


  • 虚拟机'转'是将一个宏任务从VM宏任务队列中拉出来并执行它。

  • 在虚拟机转弯期间,微任务可以添加到当前宏的微任务队列中任务。

  • 微任务可以将其他微任务推送到当前宏任务的微任务队列。

  • 当微观任务时,VM转向将结束任务队列是空的。

  • A VM 'turn' is the fact of pulling ONE macro task out of the VM macro task queue, and execute it.
  • During a VM turn, micro tasks can be added to the micro tasks queue of the current macro task.
  • Micro tasks can push other micro tasks to the micro tasks queue of the current macro task.
  • A VM turn will end when the micro task queue is empty.

以下是我的问题所在:

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


  • pushToMacroTask(功能)

  • pushToMicroTask(函数)

  • pushToMacroTask( function )
  • pushToMicroTask( function )

实际上,接触操作这些队列的唯一方法就是使用 setTimeout()来添加任务到宏任务队列和 Promises 将任务添加到微任务队列......

Actually it seams like the only way to manipulate those queue is to use setTimeout() to add tasks to the macro tasks queue and Promises to add tasks to the micro tasks queue...

我没事有这个,但是这并没有给我们一个有意义的API,你不觉得吗?

I'm ok with that but this does not give us a meaningfull API, don't you think ?

这个概念是否应该保留给JS开发者隐藏并仅用于某些hacky情况?

Is this concept supposed to remain 'hidden' to JS dev and only used in some hacky situations ?

您是否知道该主题是否有任何W3C规范?

Do you know if there is any W3C spec around that subject ?

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

Does all VM engines implement this concept the same way ?

我很乐意听到有关此事的故事和意见。

I'd be glad to ear stories and opinions about that.

谢谢!

推荐答案

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



W3C谈到任务队列


何时用户代理要对任务进行排队,它必须将给定任务添加到相关事件循环的任务队列之一。来自一个特定任务源的所有任务(例如,计时器生成的回调,为鼠标移动调度的事件,排队等待解析器的任务)必须始终添加到同一任务队列中,但可以将来自不同任务源的任务放入不同的任务队列。

When a user agent is to queue a task, it must add the given task to one of the task queues of the relevant event loop. All the tasks from one particular task source (e.g. the callbacks generated by timers, the events dispatched for mouse movements, the tasks queued for the parser) must always be added to the same task queue, but tasks from different task sources may be placed in different task queues.

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

EcmaScript2015 speaks of Job Queues, and requires that at least two are supported:



  • ScriptJobs:验证和评估ECMAScript脚本和模块源文本的作业。

  • PromiseJobs:作为答复解决Promise的工作。

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

This language definition is ignorant of a possible event loop, but one can imagine one or more Job Queues being reserved for use with the Task Queues mentioned in the W3C specs. A browser will trigger the setTimeout callback according to the W3C Task Queue specification -- linked to a Job Queue --, while a promise must use the Job Queue specification directly (not the Task Queue). That an agent could inject tasks into a Job Queue is mentioned as well:


或者,[实现]可能会选择等待一些实现特定的代理或机制以排队新的PendingJob请求。

Alternatively, [an implementation] might choose to wait for a some implementation specific agent or mechanism to enqueue new PendingJob requests.

EcmaScript规范不强制为服务不同的作业队列强制执行:

The EcmaScript specs do not enforce a priority for servicing different Job Queues:


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

This specification does not define the order in which multiple Job Queues are serviced. An ECMAScript implementation may interweave the FIFO evaluation of the PendingJob records of a Job Queue with the evaluation of the PendingJob records of one or more other Job Queues.

因此,似乎没有严格的要求,承诺履行应该在 setTimeout 任务。但是,当涉及事件循环时,Web超文本应用技术工作组更具体。

So, there seems no strict requirement here that promise fulfilments should be serviced before setTimeout tasks. But the Web Hypertext Application Technology Working Group is more specific when covering event loops:


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

Each event loop has a microtask queue. A microtask is a task that is originally to be queued on the microtask queue rather than a task queue.



所有VM引擎都以同样的方式实现吗?



这< a href =https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/\"rel =noreferrer>文章可能是一篇有趣的读物,展示了不同浏览器的实现如何导致不同执行命令:

Do all VM engines implement this the same way?

This article might be an interesting read that shows how different browser's implementations lead to different orders of execution:


某些浏览器在 setTimeout 。很可能他们将承诺回调称为新任务的一部分而不是微任务。

Some browsers [...] are running promise callbacks after setTimeout. It's likely that they're calling promise callbacks as part of a new task rather than as a microtask.

Firefox Safari 正在耗尽点击侦听器之间的微任务队列,如变异回调所示,但承诺似乎排队不同。 [...]使用 Edge ,我们已经看到它的队列承诺不正确,但它也无法耗尽点击侦听器之间的微任务队列,而是在调用所有侦听器后这样做。

Firefox and Safari are correctly exhausting the microtask queue between click listeners, as shown by the mutation callbacks, but promises appear to be queued differently. [...] With Edge we've already seen it queue promises incorrectly, but it also fails to exhaust the microtask queue between click listeners, instead it does so after calling all listeners.

本文写于2015年8月,此后几个问题已经解决并统一。

This article was written in August 2015, and since then several issues have been solved and harmonised.

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

Note however that there does not have to be one micro task queue, nor one macro task queue. There can be several queues, each with their own priority.

当然不是很难实现你建议的两个函数:

It is of course not so difficult to implement the two functions you suggested:

let pushToMicroTask = f => Promise.resolve().then(f);
let pushToMacroTask = f => setTimeout(f);
let say = msg => console.log(msg);

pushToMacroTask(say.bind(null, 'Macro task runs last'));
pushToMicroTask(say.bind(null, 'Micro task runs first'));

这篇关于Javascript API,用于显式添加微任务或宏任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆