对于 javascript 爱好者,
您将如何编程setTimeOut
(或setInterval
)句柄以按分钟触发。例如,如果是当前时间的 51 秒,则在 9 秒内触发,如果是第 14 秒,则在 46 秒内触发
谢谢
对于 javascript 爱好者,
您将如何编程setTimeOut
(或setInterval
)句柄以按分钟触发。例如,如果是当前时间的 51 秒,则在 9 秒内触发,如果是第 14 秒,则在 46 秒内触发
谢谢
var date = new Date();
setTimeout(function() {
setInterval(myFunction, 60000);
myFunction();
}, (60 - date.getSeconds()) * 1000);
显然这不是 100% 精确的,但对于大多数情况来说应该足够了。
首先,让我们确保我们知道到下一分钟还有多少时间:
var toExactMinute = 60000 - (new Date().getTime() % 60000);
现在,如果您想使用setTimeout
,那么
setTimeout(yourfunction, toExactMinute);
如果你想做一个setInterval
:
setTimeout(function() {
setInterval(yourFunction, 60000);
yourFunction();
}, toExactMinute);
var nextTick = function() {
return 60000 - (new Date().getTime() % 60000);
}, timerFunction = function() {
// do stuff
// do stuff
// do stuff
setTimeout(timerFunction, nextTick());
};
var timeout = setTimeout(timerFunction, nextTick());
起初,我使用了 Joel Potter 提出的解决方案。在大多数情况下,他的解决方案已经足够好了。但是,因为 javascript 一次只做一件事(除非您使用的是 Workers),所以第一次超时可能会迟到,所以您的第一次超时会被执行,例如。5 秒太晚了,你会在一分钟后每 5 秒获得一次间隔。
所以,这是我的实现:
function setMyFunctionInterval()
{
var currentDateSeconds = new Date().getSeconds();
if (currentDateSeconds == 0) {
setInterval(myFunction, 60000);
}
else {
setTimeout(function () {
setMyFunctionInterval();
}, (60 - currentDateSeconds) * 1000);
}
myFunction();
}
setMyFunctionInterval();
var seconds = (new Date()).getSeconds();
用作60-seconds
超时时间。当然,setTimeout
允许您指定毫秒,这意味着您还应该检查毫秒,但这将使您“足够接近”大多数应用程序。如果有的话,这应该会让你在几分之一秒内过冲,但过冲总比过冲好。使用这种方法,下冲将导致灾难性故障。
var d = new Date();
var milisecondsUntilMinuteChanges = 60000 - d.getMilliseconds() - (1000 * d.getSeconds());
虽然为时已晚,但我最近有类似的问题要解决,并想分享我的方法。我的问题是根据距离一分钟的距离在指定秒后运行超时,然后每分钟运行间隔函数。这就是我所做的。
假设日期是使用创建的javascript日期对象date = new Date();
secondsLeft = 60 - date.getSeconds();
然后设置一个超时函数在 之后运行secondsLeft
,并在函数内部设置一个间隔函数以每分钟运行一次:
setTimeout(function() {
// perform the action **A**;
minuteMS = 60 * 1000; // seconds * milliSeconds
setIntervalId = setInterval(function() {
// perform the action **A**;
}, minuteMS);
}, secondsLeft);
function waitForNewMinute() {
if (new Date().getSeconds()>1) {
setTimeout(waitForNewMinute, 500);
} else {
setInterval(doMyThing,60000);
}
}
waitForNewMinute();
我使用了'(60 - date.getSeconds()) * 1000);' 数据刷新功能上的方法,虽然它有效,但随着时间的推移它“漂移”(在我改变它之前晚了 14 秒!)
由于需要立即更新数据(这显然没有发生,因为我们在同一页面上有一个时钟!),这是我想出的解决方案:
setInterval(function () {
if(moment().format('ss') === "00"){
console.log('we are at the 0 - update the data!');
refresh_data();
}
}, 1000);
这当然使用 moment.js 来查找“0”时间,它肯定会按照 OP 的要求进行 - 每分钟都会触发 - 每次!
我相信所有的答案都是有缺陷的。一旦启动了 setInterval,间隔时间就不能在不创建新的 setInterval 对象的情况下更改。因此,您将只使用每次迭代的初始计算时间。您可以创建新的 setInterval 对象,但是这样做成本很高。
我的建议是创建一个使用 setTimeout 的循环函数。
这是一些代码:
var duration = 5; //in minutes. This is just to control the total length
var startTime = new Date().getTime(); //must be in milliseconds
function myOnTheMinuteTimer(){
setTimeout(function(){
var currentTimeMS = new Date().getTime();
var diffMs = Math.abs(startTime - currentTimeMS);
diffMs = diffMs/1000; //take out the milliseconds
var seconds = Math.floor(diffMs % 60);
diffMs = diffMs/60;
var minutes = Math.floor(diffMs % 60);
var minutesLeft = duration - minutes;
console.log("Time passed:", minutes + "m :" + seconds + "s");
if(minutes <= duration){
console.log("Timer expired.");
} else {
myOnTheMinuteTimer();
}
}, setIntervalTimeToNextMinute());
}
//Initialize timer
myOnTheMinuteTimer();
//Get our time until the next minute
function setIntervalTimeToNextMinute(){
var currentDateSeconds = new Date().getSeconds();
if(currentDateSeconds == 0){
return 60000;
} else {
return (60 - currentDateSeconds) * 1000;
}
}
我的用例是会话超时:
startTime - 允许我通过任何毫秒的时间。这样我可以避免页面加载的失误。假设用户在某个时间登录。我捕获了那个时间,然后将它传递给初始函数,它将调整回按分钟计算。
持续时间- 我使用持续时间检查进行超时设置。如果应用程序有 20 分钟的超时,那么我需要将用户路由到登录屏幕。
可选 - 您可以添加更多变体。假设您希望给用户 2 分钟的警告,告知他们将被注销。只需添加条件 an else if 2 分钟。
希望有帮助!快乐编码!
这实际上可以通过与 结合相当简单地setTimeout
完成setInterval
。我将首先以长格式演示如何做到这一点,然后在下面提供一个速记单行函数,它将完成同样的事情。
function setEmomInterval(expr, ...rest) {
setTimeout(function() {
expr(...rest);
setInterval(expr, 60000, ...rest);
}, 60000 - new Date().getTime() % (60 * 1000));
}
setEmomInterval(() => console.log(`The time is now ${new Date().getHours()}:${new Date().getMinutes()}`));
这具有额外的好处,不仅精确到秒,而且实际上精确到毫秒,减去由于计算时间导致的任何最小延迟。
作为单线,它看起来像这样:
const setEmomInterval = (expr, ...rest) => setTimeout(() => (expr(...rest), setInterval(expr, 60000, ...rest)), 60000 - new Date().getTime() % (60 * 1000));
setEmomInterval(() => console.log(`The time is now ${new Date().getHours()}:${new Date().getMinutes()}`));
如前所述,由于计算时间中所谓的“漂移”而存在一些延迟。要解决此问题,如果您需要最准确的时间,请使用Dan Kaplun 的无漂移库(GitHub 上的 @dbkaplun )。