JavaScript:如何每小时做一件事?
我想每小时执行一些JS代码。但是我不能用JavaScript:如何每小时做一件事?,javascript,time,timer,setinterval,Javascript,Time,Timer,Setinterval,我想每小时执行一些JS代码。但是我不能用 setInterval("javascript function",60*60*1000); 因为我想每一个小时做一次,我的意思是在1:00,2:00,3:00等等。我在想类似的事情 var d; while(true) { d = new Date(); if ((d.getMinutes() == '00') && (d.getSeconds() == '00')){ // my code here } }
setInterval("javascript function",60*60*1000);
因为我想每一个小时做一次,我的意思是在1:00,2:00,3:00等等。我在想类似的事情
var d;
while(true) {
d = new Date();
if ((d.getMinutes() == '00') && (d.getSeconds() == '00')){
// my code here
}
}
但是它太慢了,而且不好用
了解你的想法,你可以做的是每分钟运行一次间隔,在运行实际代码之前检查时间是否为
:00
。我会找出现在是什么时间,计算到下一个完整小时有多长时间,然后等那么长时间。所以
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
,从而陷入疯狂循环。看看这个:
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);
}
您需要每分钟运行一次setInterval函数(或每秒钟运行一次,具体取决于您希望计时器的准确性),并在分钟数为零时执行代码(顺便说一句,get minutes返回一个介于0和59之间的数字) 如果您不想在确定自己已满一小时后每隔一秒/分钟运行一次时间间隔,只需触发一个新的小时间隔并清除初始时间间隔即可
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)
您可以通过每次清除并设置间隔来完成。这只是第一次,间隔不是一小时,而是一小时减去当前的分和秒:
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 );
}
这里有一个每分钟都会更新的概念证明(我不想等一个小时来测试我的代码!):一个简单的方法是持续运行检查,以检测时间的变化:
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);
如果你像上面那样每秒钟运行一次,脚本最迟会在新的一小时内触发一秒钟
我认为这种方法既健壮又容易理解,从性能的角度来看,每秒运行一次这个简单的检查应该不是什么问题。也在寻找这个方法,根据Mark的回答,我写了以下内容:
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);
}
下面是我将如何进行的,在前面的答案的基础上进行扩展:
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
runEveryFullHours(() => console.log('Run Every Full Hours.'));
您可以使用下面的功能,这很容易适应您的需要 它计算到下一个间隔的时间,然后在每次运行脚本后重新运行脚本(除非将第3个参数设置为true) 用法示例:
// 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'));
ES6版本,适用于NodeJ和现代浏览器-根据浏览器或服务器时钟以毫秒为单位执行 功能:
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
用法:
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
建议改进Steffan提出的方法,这个方法对我最有效 功能:
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
let doSomething=函数(间隔、任务){
让运行=错误
让nextExec=()=>{
如果(间隔<0)间隔=1000
返回间隔-(新建日期().getTime()%interval)
}
让taskwrapper=()=>{
//log(“做更多…”)
任务()
}
让触发器=()=>{
如果(nextCall)清除超时(nextCall)
如果(正在运行){
nextCall=setTimeout(()=>{
taskwrapper()
触发器()
},nextExec())
}
}
设nextCall=null
返回{
下一个(){
返回正在运行的?nextExec():-1
},
行政长官(){
taskwrapper()
},
停止(){
如果(nextCall)清除超时(nextCall)
运行=错误
},
开始(){
如果(!正在运行){
运行=真
如果(nextCall)清除超时(nextCall)
触发器()
}
}
}
}
/*实例化对象doSomething(间隔、任务)*/
让obj=doSomething(5000,()=>console.log('yougo..!'))
/*安排你去。。。!每5秒*/
obj.start()
/*停止打印*/
//对象停止()
/*执行一次任务*/
obj.exec()
使用一个包装器函数,该函数将每秒执行一次,直到整小时结束,然后将调用
setInterval(cb,60*60*1000)
,然后停止执行。使用Cron作业将适合代替纯js实现
var CronJob=require('cron')。CronJob;
var job=new CronJob('**',function(){
log('您将每秒看到此消息');
}“@hourly”,真的,“America/Los_Angeles”);
job.start();
- 希罗库-
- 自动气象站
crontab
可能是比在脚本中每小时制定一次计划更好的解决方案
高性能&简短回答:
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);
};
用法:
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
runEveryFullHours(() => console.log('Run Every Full Hours.'));
“太慢”是个委婉的说法,对吧?这将彻底冻结你的浏览器永远!背景是什么?似乎在服务器上有更好的解决方案,比如Cron作业之类的。。。。但是很难说,不知道它的用途。你需要记住在设置新的间隔之前清除旧的间隔…否则很好。更高的要求/更低的兼容性,并且不包含在一个干净的可调用/命名函数中?