Is there a faster alternative to window.requestAnimationFrame()
for endless loops that don't block I/O?
What I'm doing in the loop isn't related to animation so I don't care when the next frame is ready, and I have read that window.requestAnimationFrame()
is capped by the monitor's refresh rate or at least waits until a frame can be drawn.
I have tried the following as well:
function myLoop() {
// stuff in loop
setTimeout(myLoop, 4);
}
(The 4 is because that is the minimum interval in setTimeout
and smaller values will still default to 4.) However, I need better resolution than this.
Is there anything with even better performance out there?
I basically need a non-blocking version of while(true)
.
there are some libs that can work like cron task, e.g., https://www.npmjs.com/package/node-cron
i think that using cron should be easier, and more flexible.
Two things that will run sooner than that
setTimeout
:process.nextTick
callbacks (NodeJS-specific):Promise settlement notifications
So those might be a tools for your toolbelt, doing a mix of one or both of those with
setTimeout
to achieve the balance you want.Details:
As you probably know, a given JavaScript thread runs on the basis of a task queue (the spec calls it a job queue); and as you probably know, there's one main default UI thread in browsers and NodeJS runs a single thread.
But in fact, there are at least two task queues in modern implementations: The main one we all think of (where
setTimeout
and event handlers put their tasks), and the "microtask" queue where certain async operations are placed during the processing of a main task (or "macrotask"). Those microtasks are processed as soon as the macrotask completes, before the next macrotask in the main queue — even if that next macrotask was queued before the microtasks were.nextTick
callbacks and promise settlement notifications are both microtasks. So scheduling either schedules an async callback, but one which will happen before the next main task.We can see that in the browser with
setInterval
and a promise resolution chain:When you run that and click the Hog button, note how the counter display freezes, then keeps going again. That's because of the 300,000 microtasks that get scheduled ahead of it. Also note the timestamps on the three log messages we write (they don't appear in the snippet console until a macrotask displays them, but the timestamps show us when they were logged).
So basically, you could schedule a bunch of microtasks, and periodically let those run out and run the next macrotask.
Note: I've used
setInterval
for the browser example in the snippet, butsetInterval
, specifically, may not be a good choice for a similar experiment using NodeJS, as NodeJS'ssetInterval
is a bit different from the one in browsers and has some surprising timing characteristics.