setInterval, clearInterval & formatting time
Timers and intervals
Lesson 19 of 20 · 13 min · Module 6: Timers and the capstone
Countdowns, clocks, slideshows and auto-save all run code again and again on a schedule. setInterval does exactly that, and keeping its id lets you pause, resume and reset without ever running two timers at once.
Start this lesson →Free. No installation: you write and run the code in your browser, and it is checked automatically.
By the end, you’ll be able to…
- Repeat work with setInterval and stop it with clearInterval
- Pause, resume and reset without duplicate timers
- Format seconds as minutes and seconds
The idea
setInterval(fn, 1000) calls fn every second and returns an id; clearInterval(id) stops it. Keep the remaining time in a variable, change it in the interval, and redraw the display with one render() function. Store the interval id too: null means stopped, which makes the Start/Pause button easy to write.
let seconds = 0;
const id = setInterval(() => {
seconds += 1;
console.log(seconds);
if (seconds === 3) clearInterval(id);
}, 1000);
01The id is the handle
setInterval returns an id, and clearInterval(id) is the only way to stop that timer. Starting a second interval into the same variable loses the first id, and the first timer keeps running with nothing left to stop it.
let id = setInterval(tick, 1000);
id = setInterval(tick, 1000); // the first timer still runs
02null means stopped
Setting the id back to null after clearing it gives you one simple question: if (intervalId), the timer is running. The Start/Pause text and the protection against double timers both follow from that variable.
03Timers are not clocks
Browsers delay timers in background tabs and on busy pages, so counting ticks can fall behind. For precise timers, store the end time and work out what is left on every tick.
const end = Date.now() + remaining * 1000;
// on every tick:
remaining = Math.max(0, Math.round((end - Date.now()) / 1000));
Your turn
data-seconds on #timer and show it in #time as minutes and two-digit seconds, such as 1:30; 2) #start starts a countdown that takes one second off every 1000 ms, and its text becomes Pause; clicking it again pauses, and the text goes back to Start; 3) #reset stops the timer and shows the full time again; 4) at 0:00, stop, write Time's up! in #status and disable #start; Reset enables it again and clears the status. Never run more than one interval at a time.What the checks look for
- The time comes from data-seconds
- Minutes and seconds are formatted
- Start counts down once a second
- Pause stops the countdown
- Start continues from where it paused
- Only one interval runs at a time
- Reset stops the timer and starts over
- At 0:00 it stops and says Time's up!
- Reset gets a finished timer ready again
Take this with you
Keep the interval id, clear it before starting again, and render from state.
Go a little further
Rewrite the countdown with Date.now() so it stays accurate even when the tab is in the background.