我想每小时执行一些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
}
}
但它太慢而且效果不好。
告诉你任何想法
答案 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/