later
later copied to clipboard
Minimum time to fire setTimeout should be documented
I just discovered that when doing a later.setTimeout
, it skips the first occurrence when it is within 1 second from now. Shouldn't this behaviour (see settimeout.js line 37) be documented?
Being dependent on later.setTimeout
, later.setTimeout
is affected as well. I guess the skipping of occurrences can lead to even more unexpected results there.
What's the reason behind the minimum delay?
The reason appears to be that it's a fudge factor to combat the issue with the function executing earlier than expected: https://github.com/bunkat/later/issues/90#issuecomment-101754640
However, sometimes 1 second is not enough, causing the function to execute twice: https://github.com/bunkat/later/issues/90 https://github.com/bunkat/later/issues/99 https://github.com/bunkat/later/issues/146 https://github.com/bunkat/later/issues/81
Ah, I see! A more robust solution, in my opinion, would be to make sure the timer callback isn't called prematurely. Wrapping setTimeout with something analogous to this would help:
var MAX_DELAY = 2147483647;
function setRobustTimer(fn, targetTimestamp) {
var delay = targetTimestamp - Date.now();
if (delay < 0) delay = 0; // Just to be sure, it might not be needed
if (delay > MAX_DELAY) delay = MAX_DELAY; // To solve issue #162 as well
setTimeout(function () {
var now = Date.now();
if (now >= targetTimestamp) {
fn();
} else {
// Oops, too early! Let's add some additional delay
setRobustTimer(fn, targetTimestamp);
}
}, delay);
}
This snippet is just to explain what I mean, of course. It doesn't include any logic to clear the timer. As a bonus it solves issue #162 as well. Unfortunately it doesn't solve the issue of executing the later.setInterval
callback to few times because the timer triggers too late.
An alternative solution is to avoid the use of Date.now()
in later.setTimeout
. When the caller (later.setInterval
in our case) supplies the value for now
it can use the time it was supposed to trigger instead of the time it actually did. That way it doesn't matter whether it triggered too early or too late, it won't execute the callback too many or too few times. (I hope I'm explaining it clearly)