NodeJS `setTimeout` 可以等待多长时间?

问题描述 投票:0回答:3

NodeJS

setTimeout
可以延迟一周执行函数吗? (假设服务器没有宕机...) 在其他一些服务器(例如 ASP.NET CORE)中,服务器在不使用时会休眠,因此我们不能使用它。

NodeJS 世界中是否也会发生同样的情况,或者服务器永远保持开启状态?

javascript node.js server settimeout
3个回答
3
投票

回答你的问题

setTimeout 的第二个延迟参数是 32 位有符号整数。所以该值不能大于2147483647(约24.8天)。当延迟大于2147483647时,日期将设置为1。(ref)

回答您的用例

您可以运行

cron
作业,而不是使用 setTimeout 来实现这么长的延迟。


3
投票

文档中没有任何内容表明它不起作用。但是,如果以毫秒为单位的长度大于

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


0
投票

这里有一个使超时时间超过 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
}
© www.soinside.com 2019 - 2024. All rights reserved.