NodeJS
setTimeout
可以延迟一周执行函数吗? (假设服务器没有宕机...)
在其他一些服务器(例如 ASP.NET CORE)中,服务器在不使用时会休眠,因此我们不能使用它。
NodeJS 世界中是否也会发生同样的情况,或者服务器永远保持开启状态?
回答你的问题
setTimeout 的第二个延迟参数是 32 位有符号整数。所以该值不能大于2147483647(约24.8天)。当延迟大于2147483647时,日期将设置为1。(ref)
回答您的用例
您可以运行
cron作业,而不是使用
setTimeout
来实现这么长的延迟。
文档中没有任何内容表明它不起作用。但是,如果以毫秒为单位的长度大于
2147483647
(24 天 20 小时 31 分 24 秒),则延迟设置为 1.
https://nodejs.org/api/timers.html#timers_settimeout_callback_delay_args
浏览器上的行为有所不同。毫不奇怪,如果关联的选项卡处于非活动状态,超时会延迟。
如果方法上下文是Window对象,则等到Document 与方法上下文关联已完全激活以进行进一步的操作 超时毫秒(不一定连续)。
否则,如果方法上下文是 WorkerUtils 对象,则等到 超时毫秒已经过去,工作人员没有暂停(不是 必须连续)。
https://www.w3.org/TR/2011/WD-html5-20110525/timers.html#dom-windowtimers-settimeout
这里有一个使超时时间超过 24.8 天的解决方案。 对于那些正在寻找的人。
/**
* If the timeout is greater than `maxDelay`, it calculates the number of
* expected ticks required to achieve the desired timeout duration.
*
* It then sets up an interval with a callback function that decrements the
* expectedTicks count on each tick.
*
* When expectedTicks reaches zero, it invokes the original callback with the
* provided arguments and clears the interval.
*
* If the timeout is within the maximum limit, it falls back to using the
* standard setTimeout.
*
* @author jimmy warting
* @param {(...rest) => void} callback
* @param {number} timeout
* @returns {number}
*/
function setLongTimeout (callback, timeout, ...args) {
const maxDelay = 2 ** 31 - 1
if (timeout > maxDelay) {
let expectedTicks = Math.ceil(timeout / maxDelay)
const id = setInterval(() => {
if (!--expectedTicks) {
callback(...args)
clearInterval(id)
}
}, timeout / expectedTicks)
return id
}
// If the delay is within the maximum limit, use regular setTimeout
return setTimeout(callback, timeout, ...args)
}
console.time('setLongTimeout')
// Usage example with additional arguments
const timeoutId = setLongTimeout(function(foo, bar) {
console.timeEnd('setLongTimeout')
}, 1500, 'Hello, world!', 123);
它只会创建一个单独的计时器ID,因此不必创建任何具有动态更新ID或自定义清除功能的自定义类。
clearTimeout(timeoutId)
在间隔定时器上也能正常工作。
这是一个更排序的版本:
function setLongTimeout (callback, t, ...args) {
let i = Math.ceil(t / 2 ** 31 - 1),
id = setInterval(() => {
--i || clearInterval(id, callback(...args))
}, t / i)
return id
}