admin管理员组文章数量:1356451
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.
Here is what i understand about that:
- 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.
And here is the point of my question:
Why there is no clear API to manipulate those two queues.
Something like
pushToMacroTask( function )
pushToMicroTask( function )
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...
I'm ok with that but this does not give us a meaningfull API, don't you think ?
Is this concept supposed to remain 'hidden' to JS dev and only used in some hacky situations ?
Do you know if there is any W3C spec around that subject ?
Does all VM engines implement this concept the same way ?
I'd be glad to ear stories and opinions about that.
Thanks !
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.
Here is what i understand about that:
- 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.
And here is the point of my question:
Why there is no clear API to manipulate those two queues.
Something like
pushToMacroTask( function )
pushToMicroTask( function )
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...
I'm ok with that but this does not give us a meaningfull API, don't you think ?
Is this concept supposed to remain 'hidden' to JS dev and only used in some hacky situations ?
Do you know if there is any W3C spec around that subject ?
Does all VM engines implement this concept the same way ?
I'd be glad to ear stories and opinions about that.
Thanks !
Share Improve this question edited Jan 15, 2017 at 2:40 Seki 11.5k7 gold badges48 silver badges72 bronze badges asked Dec 10, 2016 at 12:51 ClementClement 4,0785 gold badges26 silver badges38 bronze badges 3- Actually there are multiple macro tasks queues for the different event sources. – Bergi Commented Dec 10, 2016 at 14:57
- What do you mean ? Can you elaborate a bit ? Thanks – Clement Commented Dec 10, 2016 at 14:58
- Yes, I think this is supposed to be an implementation detail. The VM is supposed to optimise its scheduling on its own, adapted to the different use cases (promises, timeouts, dom events, network events etc). If you need control over this process, write your own scheduler. – Bergi Commented Dec 10, 2016 at 15:00
1 Answer
Reset to default 11Is there is any W3C spec concerning micro/macro tasks?
W3C speaks of task queues:
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 speaks of Job Queues, and requires that at least two are supported:
- ScriptJobs: Jobs that validate and evaluate ECMAScript Script and Module source text.
- PromiseJobs: Jobs that are responses to the settlement of a Promise.
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:
Alternatively, [an implementation] might choose to wait for a some implementation specific agent or mechanism to enqueue new PendingJob requests.
The EcmaScript specs do not enforce a priority for servicing different Job Queues:
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.
So, there seems no strict requirement here that promise fulfillments should be serviced before setTimeout
tasks. But the Web Hypertext Application Technology Working Group [WHATWG] 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.
[2019 addition]: In the mean time the Living HTML Standard [WHATWG] now includes the following:
8.6 Microtask queuing
self.queueMicrotask(callback)
Queues a microtask to run the given callback.
The
queueMicrotask(callback)
method must queue a microtask to invokecallback
, and ifcallback
throws an exception, report the exception.The
queueMicrotask()
method allows authors to schedule a callback on the microtask queue. This allows their code to run after the currently-executing task has run to pletion and the JavaScript execution context stack is empty, but without yielding control back to the event loop, as would be the case when using, for example,setTimeout(f, 0)
.
Do all VM engines implement this the same way?
Historically, different browser's implementations lead to different orders of execution. This article from 2015 might be an interesting read to see how different they were:
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 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 queues promises incorrectly, but it also fails to exhaust the microtask queue between click listeners, instead it does so after calling all listeners.
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.
A meaningful API
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);
pushToMacroTask(() => console.log('Macro task runs last'));
pushToMicroTask(() => console.log('Micro task runs first'));
[2019] And now that we have queueMicrotask()
, there is a native implementation. Here is a demo paring that method with the Promise-based implementation above:
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'));
本文标签: asynchronousJavascript API to explicitly add micro tasks or macro tasksStack Overflow
版权声明:本文标题:asynchronous - Javascript API to explicitly add micro tasks or macro tasks - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744059031a2583785.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论