-
Notifications
You must be signed in to change notification settings - Fork 7.3k
setTimeout fired immediately if delay is far future #8656
Comments
Reproduced using |
It is also reproducible using |
Explanation from https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers.setTimeout:
This is not so much a problem in the browser but it can be on server side (we ran into it too). Would be nice to have a helper function in node to set long timeouts. |
Actually timeout has it's max value on node.js, that is 2147483647 (2^31-1) if (!(after >= 1 && after <= TIMEOUT_MAX)) {
after = 1;
} and 1000_60_60_24_25 > 2147483647 |
Just to point out... the maximum timeout is clearly pointed out in the docs (http://nodejs.org/api/all.html#all_settimeout_cb_ms) ... Setting timeouts so far in the future seems questionable, but if you really need something like that, you can work around the max timeout limit using something like the following: function setLongTimeout(callback, ms) {
if (typeof callback !== 'function')
throw new Error('Callback must be a function');
ms = parseInt(ms);
if (Number.isNaN(ms))
throw new Error('Delay must be an integer');
var args = Array.prototype.slice.call(arguments,2);
var cb = callback.bind.apply(callback, [this].concat(args));
var longTimeout = {
timer: null,
clear: function() {
if (this.timer)
clearTimeout(this.timer);
}
};
var max = 2147483647;
if (ms <= max)
longTimeout.timer = setTimeout(cb, ms);
else {
var count = Math.floor(ms / max); // the number of times we need to delay by max
var rem = ms % max; // the length of the final delay
(function delay() {
if (count > 0) {
count--;
longTimeout.timer = setTimeout(delay, max);
} else {
longTimeout.timer = setTimeout(cb, rem);
}
})();
}
return longTimeout;
}
function clearLongTimeout(longTimeoutObject) {
if (longTimeoutObject &&
typeof longTimeoutObject.clear === 'function')
longTimeoutObject.clear()
} |
@jasnell After the above comments, I do know that it is working as designed :) You are right, that it is in rare cases that you need such long timeout, and you're suggestion is probably the workaround. As you can see in the related issue from node-bunyan, we're made a workaround much like this. Bunyan's log rotation is such an edge case, where, due to the design of the module, a long timeout is useful. I'm closing the issue |
@danieljuhl I would recommend you using https://github.com/kelektiv/node-cron#another-example-with-date combined with https://github.com/moment/moment you can specify a cronjob at a certain date:
Wouldn't it be a better solution to throw an error instead of setting the timeout to 1. |
In the future, this will emit a warning such as:
You can also use a module like |
When the following code is executed, some of the timers are fired immediately if their delay is far future (some quick testing says approx. 25 days).
Prints the following to the screen
The text was updated successfully, but these errors were encountered: