64

I am trying to repeat setTimeout every 10 seconds. I know that setTimeout by default only waits and then performs an action one time. How can I repeat the process?

setTimeout(function() {
  setTimeout(function() {
    console.log("10 seconds");
  }, 10000);
}, 10000);
hippietrail
  • 15,848
  • 18
  • 99
  • 158
Daniel
  • 4,202
  • 11
  • 50
  • 68

7 Answers7

102

Maybe you should use setInterval()

uzyn
  • 6,625
  • 5
  • 22
  • 41
  • 12
    Some additional documentation that might be useful: https://developer.mozilla.org/en/DOM/window.setInterval – vcsjones Jul 24 '12 at 04:19
  • lol ah ok thanks i didnt realize there was a delay for both setinterval and settimeout – Daniel Jul 24 '12 at 04:20
  • 6
    You didn't even provide an alternative. There are [reasons](https://stackoverflow.com/questions/729921/settimeout-or-setinterval#answer-731625) to use a repeating `setTimeout` instead of `setInterval`. You just stated the obvious, which is good because sometimes it isn't obvious, but without providing an actual answer to the original question. – NonameSL Nov 12 '17 at 15:07
53

setInterval() is probably what you're looking for, but if you want to do get the same effect with setTimeout():

function doSomething() {
    console.log("10 seconds");
    setTimeout(doSomething, 10000);
}

setTimeout(doSomething, 10000);

Or if you don't want to declare a separate function and want to stick with a function expression you need to make it a named function expression:

setTimeout(function doSomething() {
    console.log("10 seconds");
    setTimeout(doSomething, 10000);
}, 10000);

(Or use arguments.callee if you don't mind using deprecated language features.)

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
  • Instead of using `arguments.callee` which reduces performance just name your function and use that name instead. Sure it won't work in IE but I think that's a good compromise. – Aadit M Shah Jul 24 '12 at 04:39
  • 1
    @AaditMShah—what do you mean "won't work in IE"? Named function expressions are [different in IE](http://kangax.github.com/nfe/#jscript-bugs) (buggy even) but they certainly "work". – RobG Jul 24 '12 at 04:45
  • @AaditMShah - I agree with RobG on this. But hypothetically if it didn't work at all in IE, how is ignoring a browser with a large market share a "good compromise"? Anyway, you can see I only mentioned `arguments.callee` as an afterthought: I included it mainly in order to link to the MDN page on it that discusses recursive function expressions. Do you really think the reduced performance you mentioned matters with a 10 second delay, or indeed in any timeout-based algorithm which isn't really recursion at all? – nnnnnn Jul 24 '12 at 04:53
  • @nnnnnn - It has nothing to do with recursion. Using `arguments.callee` makes it difficult for the interpreter to inline a function. It certainly won't make a huge difference in this case but in critical places (like in game loops which run at 60 fps) it certainly contributes to lag. Beside named function expression simply look cleaner and I wouldn't care much for older versions of IE. They wouldn't even be able to run HTML5 games. Newer versions are finally starting to conform to the standards. – Aadit M Shah Jul 24 '12 at 09:57
20

according to me setInterval() is the best way in your case.
here is some code :

 setInterval(function() {

//your code

}, 10000); 
// you can change your delay by changing this value "10000".
Rikin Thakkar
  • 1,268
  • 3
  • 13
  • 27
19

Unlike the answers provided by @nnnnnn and @uzyn I discourage you from making use of setInterval for reasons elaborated in the following answer. Instead make use of the following Delta Timing script:

function DeltaTimer(render, interval) {
    var timeout;
    var lastTime;

    this.start = start;
    this.stop = stop;

    function start() {
        timeout = setTimeout(loop, 0);
        lastTime = + new Date;
        return lastTime;
    }

    function stop() {
        clearTimeout(timeout);
        return lastTime;
    }

    function loop() {
        var thisTime = + new Date;
        var deltaTime = thisTime - lastTime;
        var delay = Math.max(interval - deltaTime, 0);
        timeout = setTimeout(loop, delay);
        lastTime = thisTime + delay;
        render(thisTime);
    }
}

The above script runs the given render function as close as possible to the specified interval, and to answer your question it makes use of setTimeout to repeat a process. In your case you may do something as follows:

var timer = new DeltaTimer(function (time) {
    console.log("10 seconds");
}, 10000);

var start = timer.start();
Community
  • 1
  • 1
Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
  • Your funciton doesn't do what you think. `loop` is being called with an interval of zero after the first time. – RobG Jul 24 '12 at 05:25
  • @RobG - I beg to differ. When you call `start` it first calls loop with a delay of `0` ms. However browsers usually specify a minimum delay of `4` ms. After that it adjusts the delay so that it's always called at regular intervals of time. You do not need to take my word for it. See the following [fiddle](http://jsfiddle.net/AWpvu/) which logs the time difference from the time the timer starts for every second. – Aadit M Shah Jul 24 '12 at 09:50
  • Copying and pasting your code into IE 8 (and replacing `Date.now` with `new Date()` because non-ES5 browsers don't support it) results in a function that runs immediately after the first call, it doesn't wait. – RobG Jul 24 '12 at 23:18
  • 1
    Ok, found the issue. In IE 8, in addition to replacing `Date.now` with `new Date()` you need `lastTime = new Date(thisTime.getTime() + delay);` as the line in the answer results in `NaN`. Incidentally, those changes should also work in other browsers. You need to test more widely. Otherwise, your answer is good. – RobG Jul 24 '12 at 23:46
  • @RobG - I could do that or I could search for and replace all `Date.now()` with `+ new Date`. Both are the same. – Aadit M Shah Jul 25 '12 at 01:02
  • @RobG - I made the change. Check this [fiddle](http://jsfiddle.net/AWpvu/1/) to see whether it runs correctly in IE now. – Aadit M Shah Jul 25 '12 at 01:07
2
const myFunction = () => {
        setTimeout(() => {
            document.getElementById('demo').innerHTML = Date();
            myFunction();
        }, 10000);
    }

Easiest, but not efficient way!

0

Here is a function using setTimeout that tried to call itself as close as it can to a regular interval. If you watch the output, you can see the time drifting and being reset.

<script type="text/javascript">

function Timer(fn, interval) {
  this.fn = fn;
  this.interval = interval;
}

Timer.prototype.run = function() {

    var timer = this;
    var timeDiff = this.interval;
    var now = new Date();  // Date.now is not supported by IE 8
    var newInterval;

    // Only run if all is good
    if (typeof timer.interval != 'undefined' && timer.fn) {

      // Don't do this on the first run
      if (timer.lastTime) {
        timeDiff = now - timer.lastTime;
      }
      timer.lastTime = now;

      // Adjust the interval
      newInterval = 2 * timer.interval - timeDiff;

      // Do it
      timer.fn();

      // Call function again, setting its this correctly
      timer.timeout = setTimeout(function(){timer.run()}, newInterval);
  }
}


var t = new Timer(function() {
  var d = new Date();
  document.getElementById('msg').innerHTML = d + ' : ' + d.getMilliseconds();
}, 1000);


window.onload = function() {
  t.run();
};
</script>

<span id="msg"></span>
RobG
  • 142,382
  • 31
  • 172
  • 209
-1

Using jQuery, this is what you could do:

function updatePage() {

var interval = setTimeout(updatePage, 10000); // 10' Seconds

    $('a[href]').click(function() {
      $(this).data('clicked', true);
      clearInterval(interval); // Clears Upon Clicking any href Link
      console.log('Interval Cleared!');
    });
   // REPLACE 'YOUR_FUNCTION_NAME' function you would like to execute
    setTimeout(YOUR_FUNCTION_NAME, 500);

} // Function updatePage close syntax

updatePage(); // call the function again.
Shaze
  • 792
  • 1
  • 9
  • 14
  • 1
    I think you should edit the code so that it doesen't throw errors every 500 miliseconds – fourk Jun 16 '18 at 14:53