setInterval按分钟分钟

时间:2010-04-05 17:14:37

标签: javascript settimeout

对于javascript爱好者,

如何编制setTimeOut(或setInterval)句柄,以便按分钟开始。因此,例如,如果它是当前时间的51秒,那么在9秒内触发它,如果是第14秒则在46秒内触发

感谢

11 个答案:

答案 0 :(得分:17)

var date = new Date();

setTimeout(function() {
    setInterval(myFunction, 60000);
    myFunction();
}, (60 - date.getSeconds()) * 1000);

显然,这不是100%精确,但对于大多数情况来说应该足够了。

答案 1 :(得分:6)

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());

答案 2 :(得分:1)

var seconds = (new Date()).getSeconds();

使用60-seconds作为超时时间。当然,setTimeout允许您指定毫秒,这意味着您还应该检查毫秒,但这将为您提供“足够接近”的大多数应用程序。如果有的话,这应该让你在几分之一秒内超过分钟,但最好是超调而不是下冲。使用这种方法,下冲会导致灾难性的失败。

答案 3 :(得分:1)

起初,我使用了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();

答案 4 :(得分:1)

首先,让我们确定在下一分钟之前我们知道有多少时间:

var toExactMinute = 60000 - (new Date().getTime() % 60000);

现在,如果您想使用setTimeout,那么

setTimeout(yourfunction, toExactMinute);

如果你想做setInterval

setTimeout(function() {
    setInterval(yourFunction, 60000);
    yourFunction();
}, toExactTime);

答案 5 :(得分:0)

var d = new Date();
var milisecondsUntilMinuteChanges = 60000 - d.getMilliseconds() - (1000 * d.getSeconds());

答案 6 :(得分:0)

function waitForNewMinute() {
    if (new Date().getSeconds()>1) {
        setTimeout(waitForNewMinute, 500);
    } else {
        setInterval(doMyThing,60000);
    } 
}

waitForNewMinute();

答案 7 :(得分:0)

虽然回复太迟了,但我最近有类似的问题要解决,并考虑分享我的方法。我的问题是在指定的秒数后根据远离一分钟的距离运行超时,然后每分钟运行间隔功能。这就是我所做的。

假设日期是使用date = new Date();

创建的javascript日期对象
  1. 让剩下的秒数达到一分钟secondsLeft = 60 - date.getSeconds();
  2. 然后将超时功能设置为在 secondsLeft 之后运行,并在函数内部设置一个间隔函数,以便每分钟运行一次:

    setTimeout(function() {
      // perform the action **A**;
      minuteMS = 60 * 1000; // seconds * milliSeconds
      setIntervalId = setInterval(function() {
      // perform the action **A**;
     }, minuteMS);
    }, secondsLeft);
    
  3. 使用上述格式/算法,您应该能够以任何格式提供的秒数实现类似的问题。这个想法是获得秒和60之间的差异,在那些秒后运行超时,以及内部超时功能运行间隔功能,间隔为分钟/或根据要求的任何内容。

答案 8 :(得分:0)

我使用了'((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所要求的-在分钟内触发-每次!!

答案 9 :(得分:0)

我相信所有答案都是有缺陷的。启动setInterval后,如果不创建新的setInterval对象,则无法更改间隔时间。因此,您将只为每个迭代使用初始计算时间。 您可以创建新的setInterval对象,但这必须很昂贵。

请参阅:How do I reset the setInterval timer?

我的建议是创建一个使用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分钟的警告,他们将被注销。只需将有条件的else添加到条件中2分钟即可。

希望有帮助!编码愉快!

答案 10 :(得分:0)

这实际上可以通过将 setTimeoutsetInterval 结合起来相当简单地完成。我将首先演示如何以长格式执行此操作,然后在下面提供一个速记单行函数,该函数将完成相同的操作。

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 的 driftless 库(GitHub 上的 @dbkaplun)。