110

Is it possible to limit the amount of times that setInterval will fire in javascript?

Probocop
  • 10,346
  • 28
  • 85
  • 115

9 Answers9

237

You can call clearInterval() after x calls:

var x = 0;
var intervalID = setInterval(function () {

   // Your logic here

   if (++x === 5) {
       window.clearInterval(intervalID);
   }
}, 1000);

To avoid global variables, an improvement of the above would be:

function setIntervalX(callback, delay, repetitions) {
    var x = 0;
    var intervalID = window.setInterval(function () {

       callback();

       if (++x === repetitions) {
           window.clearInterval(intervalID);
       }
    }, delay);
}

Then you can call the new setInvervalX() function as follows:

// This will be repeated 5 times with 1 second intervals:
setIntervalX(function () {
    // Your logic here
}, 1000, 5);
Bill Keller
  • 793
  • 7
  • 22
Daniel Vassallo
  • 337,827
  • 72
  • 505
  • 443
  • Hey @DanielVassallo, say i want to only clear the interval on the 3rd callback because maybe finally it passed some logic; will returning false break out of setIntervalX() or will an additional parameter somewhere be needed? It looks like if i return a bool from the callback(), i can then jump out of the interval.. – Ben Sewards Feb 24 '15 at 17:15
  • Thank you very much for the useful snippet @DanielVassallo – Ana DEV Sep 28 '16 at 13:29
  • @BenSewards Where does it look like you can return a bool from the callback to jump out of the interval? You can put `clearInterval` in your callback as many times as you like and have it respond to any logic you like. There's no need to return a bool to achieve that same result. – Kyle Delaney Aug 28 '18 at 19:01
  • There are three answers that use setTimeout to clear the interval and only two that clear the interval in the interval's own callback. Why is this way better? – Kyle Delaney Aug 28 '18 at 19:03
  • @KyleDelaney I can't judge the technical quality of the answer, I just know that it is complete. For a newbie, the answer provides the function and an example of how to use the function. All the other answers are incomplete in that way and harder to use for new programmers. – Sun Sep 07 '21 at 20:22
  • when calling this function I notice a significant delay in the stimuli I have drawn to my screen - does anyone know the source of this delay or any way to quantify it? – M.L. Sep 14 '21 at 16:06
  • This is really useful for what I'm doing. Thanks very much. ❤️ – NubSteel Dec 09 '21 at 10:03
12

I personally prefer to use setTimeout() spaced out to achieve the same effect

// Set a function to run every "interval" seconds a total of "x" times
var x = 10;
var interval = 1000;

for (var i = 0; i < x; i++) {
    setTimeout(function () {
        // Do Something
    }, i * interval)
}

There's no clean up required with clearInterval()

You can enclose it to avoid variables leaking and it looks pretty clean :)

// Definition
function setIntervalLimited(callback, interval, x) {

    for (var i = 0; i < x; i++) {
        setTimeout(callback, i * interval);
    }

}

// Usage
setIntervalLimited(function() {
    console.log('hit');          // => hit...hit...etc (every second, stops after 10)
}, 1000, 10)
NDavis
  • 1,127
  • 2
  • 14
  • 23
6

You can set a timeout that calls clearInterval. This should work:

function setTimedInterval(callback, delay, timeout){
    var id=window.setInterval(callback, delay);
    window.setTimeout(function(){
        window.clearInterval(id);
    }, timeout);
}
Ben Grant
  • 305
  • 6
  • 18
blow
  • 12,811
  • 24
  • 75
  • 112
  • 2
    Wow, my answer 13 seconds later was virtualy *identical*. Freaky. – T.J. Crowder Jun 02 '10 at 10:58
  • 1
    @T.J. Sometimes I find the opposite more freaky: When we post many different solutions for one trivial problem! – Daniel Vassallo Jun 02 '10 at 11:05
  • @T.J. Crowder: Strange you using local variables and anonymous functions ;) – stagas Jun 02 '10 at 11:06
  • @T.J.Crowder thats nothing, I can clone an answer in less then 7 sec :) – Ilya Gazman Apr 04 '17 at 14:21
  • This doesn't take X into consideration. If the callback execution time > delay then it will not be fired X times, which some are after. Example: setTimedInterval(callback, 100, 1000); if callback execution is >1 00ms, then it will be probably fired a few times not 10 times. – klodoma Jul 18 '19 at 07:18
4

You can use setTimeout and a for loop.

var numberOfTimes = 20;
delay = 1000;

for (let i = 0; i < numberOfTimes; i++) {
    setTimeout( doSomething, delay * i);
}
Jerald Macachor
  • 131
  • 2
  • 4
1

This will clear the interval after 10 calls

<html>
<body>

<input type="text" id="clock" />
<script language=javascript>
var numOfCalls = 0;
var int=self.setInterval("clock()",1000);
function clock()
  {
  var d=new Date();
  var t=d.toLocaleTimeString();
  document.getElementById("clock").value=t;
  numOfCalls++;
  if(numOfCalls == 10)
     window.clearInterval(int);
  }
</script>
</form>


</body>
</html>
Amr Elgarhy
  • 66,568
  • 69
  • 184
  • 301
1

I made a small package that does this for NodeJS.

https://www.npmjs.com/package/count-interval

It's a drop-in replacement for setInterval (including parameter passing), but it takes an additional count parameter. This example prints a message once every second, but only 3 times.

const countInterval = require('./countInterval');

const timer = countInterval(() => {
   console.log('fired!', new Date());
}, 1000, 3);
jimm101
  • 948
  • 1
  • 14
  • 36
1

And for those of you preferring setTimeout and loving recursion here is my suggestion ;)

const setIntervalX = (fn, delay, times) => {
  if(!times) return

  setTimeout(() => {
    fn() 
    setIntervalX(fn, delay, times-1)
  }, delay)
}

Then as suggested you can call the new setInvervalX() function as follows:

// This will be repeated every for 5 times with 1 second intervals:
setIntervalX(function () {
    // Your logic here
}, 1000, 5);
Jonas Johansson
  • 417
  • 3
  • 8
1

You can do this actually very simply with setTimeout() and an incremental counter.

var i = 0; // counter for the timer
function doSomething() {
    console.log("1 second"); // your actual code here, alternatively call an other function here
    if (++i < 10)
    {   // only reset the timer when maximum of 10 times it is fired 
        console.log("reset the timer");
        setTimeout(doSomething, 1000); // reset the timer
    }
}
setTimeout(doSomething, 1000);  // init the first

This answer is based on SO: Repeating setTimeout and a nice, neat and tidy small combination with this.

pas-calc
  • 115
  • 9
0

You can use Six

SetIntervalX: Limit the number of times that setInterval will fire

import { setIntervalX } from "https://deno.land/x/six/mod.ts";
import { randomNumber } from "https://deno.land/x/random_number/mod.ts";

const API_URL = "https://leap.deno.dev";

async function checkAPIStatus() {
  const startTime = performance.now();

  const randomYear = randomNumber({ min: 2000, max: 10_000 });

  const response = await fetch(`${API_URL}/${randomYear}`);

  const data = await response.json();

  console.log(`Is ${randomYear} a leap year? ${data.leapYear}.`);

  const entTime = performance.now();

  console.log(`Request took ${(entTime - startTime) / 1000} seconds.`);
}

setIntervalX(checkAPIStatus, 2000, 15);

Web Page: https://ulti.js.org/six

Repository: https://github.com/UltiRequiem/six

It includes documentation, 100% code coverage, and examples!

Works on Deno, Node.js and the browser!

Eliaz Bobadilla
  • 479
  • 4
  • 16