JavaScript:如何每隔一小时做一些事情?

时间:2012-09-06 22:00:05

标签: javascript time timer setinterval

我想每小时执行一些JS代码。但我不能用

setInterval("javascript function",60*60*1000);

因为我想每隔一小时做一次,我的意思是1点,2点,3点等等。我正在考虑像

这样的东西
var d;
while(true) {
  d = new Date();
  if ((d.getMinutes() == '00') && (d.getSeconds() == '00')){
    // my code here
  }  
}

但它太慢而且效果不好。

告诉你任何想法

16 个答案:

答案 0 :(得分:10)

我会知道它现在是几点,弄清楚它会持续多长时间,直到下一个整整一个小时,然后等待那么久。所以,

function doSomething() {
    var d = new Date(),
        h = new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours() + 1, 0, 0, 0),
        e = h - d;
    if (e > 100) { // some arbitrary time period
        window.setTimeout(doSomething, e);
    }
    // your code
}

检查e < 100只是为了确保你不会在5毫秒之内做setTimeout并让它成为一个疯狂的循环。

答案 1 :(得分:6)

您可以做的是每分钟运行一次间隔,并在运行实际代码之前检查时间是否为:00

答案 2 :(得分:3)

看看这个:

function to_be_executed(){
    ...
    ...
    ...
    makeInterval();
}

function makeInterval(){
    var d = new Date();
    var min = d.getMinutes();
    var sec = d.getSeconds();

    if((min == '00') && (sec == '00'))
        to_be_executed();
    else
        setTimeout(to_be_executed,(60*(60-min)+(60-sec))*1000);
}

答案 3 :(得分:3)

高性能和简短答案

const runEveryFullHours = (callbackFn) => {
  const Hour = 60 * 60 * 1000;
  const currentDate = new Date();
  const firstCall =  Hour - (currentDate.getMinutes() * 60 + currentDate.getSeconds()) * 1000 + currentDate.getMilliseconds;
  setTimeout(() => {
    callbackFn();
    setInterval(callbackFn, Hour);
  }, firstCall);
};

用法:

runEveryFullHours(() => console.log('Run Every Full Hours...'));

答案 4 :(得分:1)

您可以通过每次清除和设置间隔来完成此操作。它只是第一次,而不是间隔为一小时,它将是一小时减去当前的分钟和秒:

var d = new Date();
var secondsPastHour = d.getMinutes()*60 + d.getSeconds();
var intervalId = setInterval( myFn, 60*60*1000 - secondsPastHour*1000 );

function myFn() {
    // do stuff
    // ...
    clearInterval( intervalId );
    intervalId = setInterval( myFn, 60*60*1000 );
}

唯一的问题是,最终它可能会开始漂移......解决方法是在函数内部执行相同的操作,就像在踢它时一样:

var d = new Date();
var secondsPastHour = d.getMinutes()*60 + d.getSeconds();
var intervalId = setInterval( myFn, 60*60*1000 - secondsPastHour*1000 );

function myFn() {
    // do stuff
    // ...
    clearInterval( intervalId );
    var d = new Date();
    var secondsPastHour = d.getMinutes()*60 + d.getSeconds();
    intervalId = setInterval( myFn, 60*60*1000 - secondsPastHour*1000 );
}

这是一个每分钟更新一次的概念证明(我不想等一整个小时来测试我的代码!):http://jsfiddle.net/dRsua/

答案 5 :(得分:0)

您需要每分钟运行一次setInterval函数(或每秒运行一次,具体取决于您希望计时器的准确程度),并在分钟为零时执行代码(顺便说一下,分钟返回0到59之间的数字).. < / p>

 function myTimer() {
        var d = new Date()
        if (d.getMinutes() == 0) {
        console.log("full hour");
        }
}

 timer = setInterval(function(){myTimer()},60000)

如果您不希望在确定完全一小时后每秒/分钟运行一次间隔,则只需触发一个新的每小时间隔并清除初始间隔。

var myHourlyTimer = null;

     function myTimer() {
            var d = new Date()
            if (d.getMinutes() == 0) {
            console.log("full hour");
myHourlyTimer = setInterval(function(){myHourlyTimerFunction()},3600000);
clearInterval(timer)
            }
    }

 timer = setInterval(function(){myTimer()},60000)

答案 6 :(得分:0)

一种简单的方法是不断运行检查以检测小时何时发生变化:

var lastProcessedHour = -1;

setInterval(function() {
   var d = new Date();
   var currentHour = d.getHours();
   if (currentHour != lastProcessedHour) {
      // do stuff
      console.log("new hour");

      lastProcessedHour = currentHour;
   }
}, 1000);

如果你像上面那样每秒运行一次,脚本最迟会在新的小时内触发一秒钟。

我认为这种方法既健壮又易于理解,从性能的角度来看,每秒运行一次这种简单的检查确实不是问题。

答案 7 :(得分:0)

根据马克的反应,我也在寻找这个,我写道:

function callEveryFullHour() {

    var now = new Date();
    var nextHour = new Date(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours() + 1, 0, 0, 0);
    var difference = nextHour - now;

    window.setTimeout(function(){

        // code goes here

        console.log("It's a full hour!")
        callEveryFullHour();

    }, difference);

}

答案 8 :(得分:0)

这就是我要做的事情,扩展上一个答案:

function callEveryFullHour(my_function) {

    var now = new Date();
    var nextHour = new Date(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours() + 1, 0, 0, 0);
    var difference = nextHour - now;

    return window.setTimeout(function(){

        // run it
        my_function();

        // schedule next run
        callEveryFullHour(my_function);

    }, difference);
}

通过这种方式,您可以开始停止任何功能在整个小时内运行。

用法:

let my_function = () => { // do something };
let timeout = callEveryHour(my_function);

// my_function will trigger every hour

window.clearTimeout(timeout);

// my_function will no longer trigger on the hour

答案 9 :(得分:0)

您可以使用类似下面的函数,它很容易满足您的需求。

它计算到下一个间隔的时间,然后每次(除非将第3个参数设置为true)运行之后,将重新运行脚本。

function runOnInterval(interval_in_ms, function_to_run, only_run_once = false){
    setTimeout(()=>{
        function_to_run();
        if (!only_run_once) runOnInterval(...arguments);
    }, interval_in_ms - ((Date.now() - (new Date().getTimezoneOffset() * 6e4)) % interval_in_ms));
}

示例用法:

// Every day at midnight:
runOnInterval(24 * 60 * 60 * 1000, my_function_to_run);
// Every hour on the hour:
runOnInterval(60 * 60 * 1000, my_function_to_run);
// Every minute on the minute:
runOnInterval(60000, my_function_to_run);
// Every 10 seconds on the 10 second mark:
runOnInterval(1e4, ()=>console.log('this will be run every 10 seconds on the 10 second mark'));

答案 10 :(得分:0)

ES6版本,可在NodeJS和现代浏览器中使用-根据浏览器或服务器时钟在毫秒内执行。

功能

const doSomething = (something) => {
  let running = true
  let nextHour = () => {
    return 3600000 - new Date().getTime() % 3600000
  }
  let nextCall = setTimeout(() => {
    something()
    doSomething(something)
  }, nextHour())
  return {
    next() { return running ? nextHour() : -1 },
    exec() { something() },
    stop() {
      clearTimeout(nextCall)
      running = false
    },
    start() {
      clearTimeout(nextCall)
      nextCall = setTimeout(() => {
        something()
        doSomething(something)
      }, nextHour())
      running = true
    }
  }
}

用法:

// Do something at next full hour and repeat forever
doSomething(() => console.log('Full hour reached!'))

// Do something every full hour & stop it
let obj = doSomething(() => console.log('Will I ever execute? :/'))
obj.next() // Time to next execution in milliseconds
obj.next() / 1000 // Time to next execution in seconds
obj.next() / 1000 / 60 // Time to next execution in minutes
obj.stop() // Stop executing every full hour
obj.start() // Continue executing every hour
obj.exec() // Execute now

答案 11 :(得分:0)

提议改进Steffan提出的方法,这一方法对我来说效果最好。

功能

let doSomething = function (interval, task) {
      let running = false
      let nextExec = () => {
        if (interval < 0) interval = 1000
        return interval - (new Date().getTime() % interval)
      }
      let taskwrapper = () => {
        //console.log("do more...")
        task()
      }
      let trigger = () => {
        if (nextCall) clearTimeout(nextCall)
        if (running) {
          nextCall = setTimeout(() => {
            taskwrapper()
            trigger()
          }, nextExec())
        }
      }
      let nextCall = null
      return {
        next() {
          return running ? nextExec() : -1
        },
        exec() {
          taskwrapper()
        },
        stop() {
          if (nextCall) clearTimeout(nextCall)
          running = false
        },
        start() {
          if (!running) {
            running = true
            if (nextCall) clearTimeout(nextCall)
            trigger()
          }
        }
      }
    }

/*instantiate an object doSomething(interval, task) */
let obj = doSomething(5000, () => console.log('You go..!'))

/*schedule You go...! every 5 seconds */
obj.start()

/*stop printing  */
//obj.stop()

/*execute task once */
obj.exec()

答案 12 :(得分:0)

let timerId = null

function wrapper (cb,date = new Date()) {
    if(!date.getMinutes() && !date.getSeconds()){
        setInterval(cb,60*60*1000);
        clearInterval(timerId)
    }
}

timerId = setInterval(wrapper,1000,yourCb)

使用一个包装器函数,该函数每秒钟执行一次,直到整整一个小时到达,然后调用setInterval(cb,60*60*1000),然后停止执行。

答案 13 :(得分:0)

使用Cron Job代替纯js实现是合适的。

var CronJob = require('cron').CronJob;
var job = new CronJob('* * * * * *', function() {
  console.log('You will see this message every second');
}, "@hourly", true, 'America/Los_Angeles');
job.start();

答案 14 :(得分:0)

答案 15 :(得分:0)

如果此脚本在类似Unix的服务器而不是浏览器上运行,那么与在脚本中每小时进行一次调度相比,crontab可能是最佳的解决方案。

https://www.geeksforgeeks.org/crontab-in-linux-with-examples/