Yes, the message queue will have higher importance than timeouts one, and will thus fire at higher frequency.
You can bind to that queue quite easily with the MessageChannel API:
let i = 0;
let j = 0;
const channel = new MessageChannel();
channel.port1.onmessage = messageLoop;
function messageLoop() {
i++;
// loop
channel.port2.postMessage("");
}
function timeoutLoop() {
j++;
setTimeout( timeoutLoop );
}
messageLoop();
timeoutLoop();
// just to log
requestAnimationFrame( display );
function display() {
log.textContent = "message: " + i + '\n' +
"timeout: " + j;
requestAnimationFrame( display );
}
<pre id="log"></pre>
Now, you may also want to batch several rounds of the same operation per event loop.
Here are a few reasons why this method works:
-
Per specs,
setTimeout
will get throttled to a minimum of 4ms after the 5th level of call, that is after the fifth iteration of OP’s loop.
Message events are not subject to this limitation. -
Some browsers will make the task initiated by
setTimeout
have a lower priority, in some cases.
Namely, Firefox does that at page loading, so that scripts callingsetTimeout
at this moment don’t block other events ; they do even create a task queue just for that.
Even if still un-specced, it seems that at least in Chrome, message events have a “user-visible” priority, which means some UI events could come first, but that’s about it. (Tested this using the up-comingscheduler.postTask()
API in Chrome) -
Most modern browsers will throttle default timeouts when the page is not visible, and this may even apply for Workers.
Message events are not subject to this limitation. -
As found by OP, Chrome does set a minimum of 1ms even for the first 5 calls.
But remember that if all these limitations have been put on setTimeout
, it’s because scheduling that many tasks at such a rate has a cost.
Use this only in a Worker thread!
Doing this in a Window context will throttle all the normal tasks the browser has to handle, but which they’ll consider less important, like Network requests, Garbage Collection etc.
Also, posting a new task means that the event loop has to run at high frequency and will never idle, which means more energy consumption.