Intervals are like timeouts that will reschedule themselves (which differs from a timeout starting a new timeout). Since intervals reschedule themselves, only create one. (Or, only as many as really necessary.)
The problem with the original post is it was creating 5 intervals (because they were being created in the loop) and then only keeping the interval ID (in counter
) of the last interval created! Thus the clearInterval
only stopped the last interval and the other 4 intervals kept running and running and running ..
Here is some cleaned up code with comments and without the original problem:
var count = 5;
// only need ONE interval
var counter = setInterval(timer, 1000);
// so we do one count RIGHT NOW
timer();
function timer() {
// display first, so we start at 5: 5, 4 .. 1
console.log(count);
count--;
if (count < 0) {
// to repeat the count, comment out the clearInterval
// and do `count = 5;` or similar .. take it from here :D
clearInterval(counter);
}
}
To create separate "state" for each countdown, either create a new countdown object that maintains state in properties or use a closure. Here is an example with a closure. I have also added support for a callback function to show how such a function can be made more generic:
function makeCountdown(startCount, delay, fn) {
fn = fn || function (i) {
// default action, if fn not specified
console.log(i);
};
// local variables
var count = startCount;
var counter = setInterval(timer, delay);
timer();
function timer() {
// now count and counter refer to variables in the closure (keyword!)
// which are different each time makeCountdown is called.
fn(count);
count--;
if (count < 0) {
clearInterval(counter);
}
}
}
makeCountdown(20, 500); // uses default function
makeCountdown(10, 1000, function (i) { console.log(10 - i) });
makeCountdown(5, 2000, function (i) { console.log("SLOW! " + i) });
Exercises:
- Add a callback function for when the countdown is "done" so that countdowns can be run in series.
- Consume a series generator and use that to generate the next
count
value.
- Have
makeCountdown
return an object that can be used to control the countdown.
- Have fun!