如何每小时调用一次函数

How to call a function every hour?

本文关键字:一次 函数 每小时 调用      更新时间:2023-09-26

我正在尝试更新页面上的天气服务信息。信息应每小时更新一次。我究竟如何每小时调用一个函数?

我有点想法,但我不确定如何实际完善它以便它起作用......我想到的是创建一个if语句,例如:(伪代码)

//get the mins of the current time
var mins = datetime.mins();    
if(mins == "00"){
    function();
 }

您想查看setInterval:https://developer.mozilla.org/en-US/docs/Web/API/Window.setInterval

很难

说出您要用代码调用什么,但它的形式是:

function callEveryHour() {
    setInterval(yourFunction, 1000 * 60 * 60);
}

如果您希望每小时一次,请尝试以下操作:

var nextDate = new Date();
if (nextDate.getMinutes() === 0) { // You can check for seconds here too
    callEveryHour()
} else {
    nextDate.setHours(nextDate.getHours() + 1);
    nextDate.setMinutes(0);
    nextDate.setSeconds(0);// I wouldn't do milliseconds too ;)
    var difference = nextDate - new Date();
    setTimeout(callEveryHour, difference);
}

现在,此实现检查一次时间,设置延迟(或立即调用函数),然后依靠 setInterval 来跟踪。 另一种方法可能是每x秒/分钟轮询一次时间,然后.getMinutes() == 0触发它(类似于if语句的第一部分),这可能会牺牲(边际)性能来换取(边际)准确性。 根据您的确切需求,我会尝试这两种解决方案。

以下是应该工作的方法(JSFiddle):

function tick() {
  //get the mins of the current time
  var mins = new Date().getMinutes();
  if (mins == "00") {
    alert('Do stuff');
  }
  console.log('Tick ' + mins);
}
setInterval(tick, 1000);

你可能想要的是这样的东西:

var now = new Date();
var delay = 60 * 60 * 1000; // 1 hour in msec
var start = delay - (now.getMinutes() * 60 + now.getSeconds()) * 1000 + now.getMilliseconds();
setTimeout(function doSomething() {
   // do the operation
   // ... your code here...
   // schedule the next tick
   setTimeout(doSomething, delay);
}, start);

所以基本上用户第一次获得访问权限时,你需要知道毫秒到下一个"小时"的延迟是多少。因此,如果用户在 8:54(56 秒和 123 毫秒)访问页面,则必须在大约 3 分钟后安排第一次执行:第一次执行完成后,您可以每隔"小时"(60 * 60 * 1000)调用一次。

在整点过后的特定分钟重复

这个计数器更通用一些;它允许总是在整点过去的同一分钟(例如,整点过后37分钟)重复执行任务,并且精度高达毫秒。

此计时器的精度派生自其递归。在每次递归时,都会重新计算到下一分钟的毫秒时间。这可以防止长时间的滞后。

%符号是指模运算符。

function minuteCount(minutesAfterHour) {
    const now          = new Date();
    const hours        = now.getHours();
    const minutes      = now.getMinutes();
    const seconds      = now.getSeconds();
    const milliseconds = now.getMilliseconds();
    waitUntilNextMinute = setTimeout(minuteCount, 60000 - seconds * 1000 - milliseconds);
    if(minutes % 60 === minutesAfterHour) {
        doSomethingHourly();
    }
}
minuteCount(37);

最后,计时器最好远离主线程。它们最好从 Web worker 内部运行,如此处所述。这非常适合桌面浏览器中未聚焦的选项卡。

但是,Android 版 Chrome 上的专用网络工作者在将主客户端移动到后台后大约 5 分钟就会进入睡眠状态。

编辑:哎呀,我没有看到"点钟"的东西,所以我编辑了我的答案:

var last_execution = new Date().getTime();
function doSomething(force){
  var current_time = new Date().getTime();
  if (force || (current_time.getMinutes() == 0)
  {
    last_execution = current_time;
    // something
    // ...
  }
  setTimeout(doSomething(false), 1000);
}
// force the first time
doSomething(true); 
// ... call your func now
let intervalId;
let timeoutId = setTimeout(() => {
  // ... call your func on end of current hour
  intervalId = setInterval(() => {
     // ... call your func on end of each next hours
  }, 3600000);
}, ((60 − moment().minutes()) × 60 × 1000) - (moment().second() * 1000));
这是我的一

setIntervalWithDelayclearIntervalWithDelay,可以这样使用:

let descriptor = setIntervalWithDelay(callback, 60 * 60 * 1000, nextHourDelay)

当你完成它时:

clearIntervalWithDelay(descriptor)

这是我对这些函数的实现:

const setIntervalWithDelay = (callback, interval, delay = 0) => {
    let descriptor = {}
    descriptor.timeoutId = setTimeout(() => {
        if(!descriptor.timeoutId){
            return
        }
        descriptor.timeoutId = null
        callback()
        descriptor.intervalId = setInterval(callback, interval)
    }, delay)
    return descriptor
}
export const clearIntervalWithDelay = (descriptor) => {
    if(!isObject(descriptor) || (!descriptor.timeoutId && !descriptor.intervalId)){
        console.warn("clearIntervalWithDelay: Incorrect descriptor. Please pass an object returned by setIntervalWithDelay. Skipping this call.")
        return
    }
    if(descriptor.timeoutId){
        clearTimeout(descriptor.timeoutId)
        descriptor.timeoutId = null
        console.log("clearIntervalWithDelay: stopped during delay.")
    }
    if(descriptor.intervalId){
        clearInterval(descriptor.intervalId)
        descriptor.intervalId = null
        console.log("clearIntervalWithDelay: stopped during interval repeat.")
    }
}

使用 dayjs 获取下一个小时的延迟的一个示例:

let nextHour = dayjs().second(0).millisecond(0).add(1, "hour")
let nextHourDelay = nextHour.diff(dayjs())