Hi,
It’s a really good question and I have plans to write an article about all these mysteries of timers in a separate article. However, since you asked I can give a minimal explanation to that.
This inconsistency is because, if the timer value if less than 1 or greater than the maximum allowed timeout, it’s set to 1ms (to follow the browser behavior as commented). Have a look at here:
function Timeout(callback, after, args, isRepeat, isUnrefed) {
after *= 1; // coalesce to number or NaN
if (!(after >= 1 && after <= TIMEOUT_MAX)) {
if (after > TIMEOUT_MAX) {
process.emitWarning(`${after} does not fit into` +
' a 32-bit signed integer.' +
'\nTimeout duration was set to 1.',
'TimeoutOverflowWarning');
}
after = 1; // schedule on next tick, follows browser behavior
}
....
}Due to this, only if it the system call takes more than 1ms, the timer will be identified as expired. And if the system call completes before 1ms, then the timer’s expiry time will be greater than the loop time and the timer won’t be identified as expired. You can try setting this to after = 0 and you’ll identify that the timer callback will always run before setImmediate callback. And if you increase it to something larger, setImmediate callback will proceed.
Hope this clarification is sufficient.
