New Version
There is no guaranteed delay. Scheduling mechanics, including the minimum amount of milliseconds of setTimeout
, depend on your JavaScript environment and/or your OS, since they are not in the official ECMA specs.
JavaScript engines generally have multiple queues that the event queue continually processes. Once the current script has finished executing (e.g. the one that calls setTimeout(someCallback)
), the loop will look through all queues, in order of priority, and execute all pending requests that are due (including someCallback
, or any other callback to a setTimeout
/setImmediate
/process.nextTick
etc. call).
Once the loop finishes an iteration, modern implementations set it up to wait for the least amount of time necessary until the next event is due, or until an external IO event wakes it up. E.g. if you have three active setTimeout
timers, it will wait for the min of the remaining time on those three timers.
Warning: Depending on queue priority, the granularity of this might vary. Note that high-resolution system timers are expensive. So if you schedule something for a low-priority queue, or the schedule time itself is high, they might opt to use a lower performance timer for the "wake-up call", meaning, things might vary a lot between different queues and delays. Also, as my tests show, Chrome does not care, and uses (quite) a high-resolution timer even for setTimeout
, (apparently).
Here are some tests I just quickly ran in Chrome and Node on Windows 10.
Code:
function testScheduler(scheduler, ms) {
function f() {
console.log(`${scheduler.name} with ${ms ? `${ms} ms` : 'no'} delay:`, performance.now() - s);
}
var s = performance.now();
scheduler(f, ms);
}
testScheduler(setTimeout, 0);
testScheduler(setTimeout, 1);
testScheduler(setTimeout, 5);
testScheduler(setTimeout, 100);
testScheduler(setImmediate);
Experiment Results:
Summary of results:
- Numbers can vary wildly.
- Node is less accurate than Chrome (despite using the same engine (V8) under the hood).
Chrome (2022/9):
(NOTE: in Chrome, setImmediate
was removed.)
setTimeout with 0 ms delay: 0.19999998807907104
setTimeout with 1 ms delay: 1.9000000357627869
setTimeout with 5 ms delay: 6.900000035762787
setTimeout with 100 ms delay: 110.5
Node@16 (some run):
setImmediate with no delay: 0.23650002479553223
setTimeout with no delay: 5.476700007915497
setTimeout with 1 ms delay: 5.6164000034332275
setTimeout with 5 ms delay: 6.091899991035461
setTimeout with 100 ms delay: 103.40990000963211
Node@16 (some other run):
setImmediate with no delay: 1.2796000242233276
setTimeout with no delay: 19.26560002565384
setTimeout with 1 ms delay: 19.923299968242645
setTimeout with 5 ms delay: 21.00239998102188
setTimeout with 100 ms delay: 107.54070001840591
System Timers
When the queue does not run right away, and when idling between iterations, then the minimum amount of milliseconds is determined by the timeslice resolution of your operating system and hardware. The smallest "sleepable" amount of time is usually the time it takes for the process to be allocated another timeslice by your system's scheduling algorithm.
On Windows (post XP) for example, Node might be using Windows' sleep
system call, for this, while the results for Chrome seem to indicate that it uses a higher resolution timer than this.