Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

To the javascript enthusiasts,

how would you program a setTimeOut (or setInterval ) handle to fire by the minute on the minute. So for example, if it is the 51 second of the current time, then fire it in 9 seconds, if it is the 14th second then fire it in 46 seconds

thanks

clarify: question is for javascript developers to show creative ways to use settimeout setinterval built in functions -- bushman Apr 5, 2010 at 17:26 Assuming processing takes some period of time, this will get off pretty quickly if myFunction takes more than 0 time, which it will. Stefan Kendall Apr 5, 2010 at 17:22 You don't need to recompute every time. I agree myFunction should be called after the interval (I edited to correct), but the delay due to setInterval will be minuscule. Joel Apr 5, 2010 at 17:24 I think the setInterval in javascript will fix itself if "myFunction" takes a while to compute. user216441 Apr 5, 2010 at 17:29 @M28, Since myFunction is a reference, it won't need to compute until the 60 seconds runs out, at which time the next interval should be set before it computes myfunction() . Joel Apr 5, 2010 at 17:32

First, let's make sure we know how much time do we have until the next minute:

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

Now, if you want to work with setTimeout, then

setTimeout(yourfunction, toExactMinute);

If you want to do a 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());
                FYI modulus % operator can be used on Date objects directly, shortening your code to 60000 - (new Date() % 60000).
– Crescent Fresh
                Apr 5, 2010 at 17:35

At first, I used the solution proposed by Joel Potter. His solution is good enough in most cases. However, because the javascript is doing one thing at a time (unless you are using Workers), it may be late with first timeout, so your first timeout is executed eg. 5 seconds too late and you get interval on every 5 seconds after the minute.

So, here is my implementation:

function setMyFunctionInterval()
    var currentDateSeconds = new Date().getSeconds();
    if (currentDateSeconds == 0) {
        setInterval(myFunction, 60000);
    else {
        setTimeout(function () {
            setMyFunctionInterval();
        }, (60 - currentDateSeconds) * 1000);
    myFunction();
setMyFunctionInterval();

Use 60-seconds as the timeout time. Granted, setTimeout lets you specify milliseconds, which means you should also be checking milliseconds, but this will give you "close enough" for most applications. If anything, this should make you overshoot the minute some fraction of a second, but it's better to overshoot than undershoot. Undershooting would cause catastrophic failure with this method.

Although too late for the response, I have had similar problem to solve recently and thought of sharing my approach. My problem was to run a timeout after a specified seconds based on how far it is away from a minute, and subsequently run interval function each minute. Here is what I did.

Let's say the date is javascript date object created using date = new Date();

  • Get the seconds left to reach a minute secondsLeft = 60 - date.getSeconds();
  • Then set a timeout function to run after secondsLeft, and inside the function set an interval function to run each minute as:

    setTimeout(function() {
      // perform the action **A**;
      minuteMS = 60 * 1000; // seconds * milliSeconds
      setIntervalId = setInterval(function() {
      // perform the action **A**;
     }, minuteMS);
    }, secondsLeft);
    
  • Using above format/algorithm you should be able to achieve similar problems be the seconds supplied in any format. The idea is to get the difference of seconds and 60, run a timeout after those seconds, and inside timeout function run interval function with interval as a minute/or anything as such based on requirement.
  • function waitForNewMinute() {
        if (new Date().getSeconds()>1) {
            setTimeout(waitForNewMinute, 500);
        } else {
            setInterval(doMyThing,60000);
    waitForNewMinute();
    

    I used the ' (60 - date.getSeconds()) * 1000);' method on a data refresh function and, while it worked, it 'drifted' over time (14 seconds late before I changed it!)

    As the data needed to be updated ON the minute (and that was obviously not happening as we have a clock on the same page!), here's the solution I came up with:

    setInterval(function () {
        if(moment().format('ss') === "00"){
            console.log('we are at the 0 - update the data!');
            refresh_data();
    }, 1000);
    

    This of course uses moment.js to find the '0' time and it certainly does what the OP asked - fires on the minute - every time!

    I believe all the answers are flawed. Once you have started the setInterval, the interval time cannot be changed without creating a new setInterval object. So you will only use the initial calculated time for each iteration. You can create new setInterval objects, but that has to be costly.

    See: How do I reset the setInterval timer?

    My recommendation is to create a looping function that utilizes the setTimeout instead.

    Here's some code:

    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;
    

    My use case for this was a session timout:

    startTime - allows me to pass in any milliseconds time. This way I can avoid lapses in page loading. Say user logins in at a certain time. I capture that time, then pass it into initial function and it will adjust back to the on minute calculation.

    duration - I use the duration check for a timeout setting. If the application has a 20 minute timeout, then I need to route the user to the login screen.

    optionally - you can add more variations. Say you wish to give the user a 2 minute warning that they will be logged out. Simply add to the conditional an else if for 2 minutes.

    Hope that helps! Happy coding!

    This can actually be done fairly simply by combining setTimeout with setInterval. I'll first demonstrate how to do this in long-form, and then provide a shorthand one-liner function below which will accomplish the same thing.

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

    This has the added benefit of not only being accurate to the second, but in fact accurate to the millisecond, minus any minimal lag due to computation time.

    As a one-liner, it would look like this:

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

    As mentioned, there is some delay due to what is known as "drift" in the computation time. To work around this, if you need the most accurate time, use the driftless library by Dan Kaplun (@dbkaplun on GitHub).

    The Above answers fulfill the job but still wanted to solve this with a better approach.

    You can solve this by using setInterval & clearInterval

    let job = setInterval(function() {
        /* Do you stuff */
    },1000);
    setTimeout(function() {
        clearInterval(job);
    },60000);
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.

  •