Build a Stopwatch
Loading simulation…
flagWhat you'll discover
- arrow_forwardSchedule repeating code with setInterval and a delay
- arrow_forwardStop a running timer with clearInterval and its id
- arrow_forwardKeep elapsed time in state variables that survive between ticks
- arrow_forwardWire three buttons to start, stop and reset behaviours
Timers: code that runs later
Everything you have written so far runs top to bottom and finishes instantly. setInterval(fn, 100) is different: it asks the browser to run your function every 100 milliseconds, forever, until told to stop. Your script ends, but the ticking continues — the browser keeps the function and fires it on schedule. This is asynchronous programming: code scheduled for the future instead of executed now. Animations, clocks, autosave, the blinking cursor in your editor — all of them are timers firing quietly in the background.
The event loop, briefly
How can a browser run your timer, listen for clicks and scroll the page all at once? Through the event loop: an endless cycle that checks a queue of waiting jobs — a timer is due, a button was clicked — and runs them one at a time, extremely fast. setInterval does not interrupt running code; it places your function into that queue each time the delay elapses. That is also why setInterval(fn, 100) means "at most every 100ms, not earlier" — if the browser is busy, your tick waits its turn in the queue.
Stopping needs a handle
setInterval returns an id — a number identifying that particular timer. Store it: timer = setInterval(...). To stop, call clearInterval(timer). Forget to store the id and the timer becomes unstoppable! There is a classic bug lurking here too: press Start twice without guarding and you create TWO timers updating the same display, making time run double-speed — and your stored id can only cancel one of them. A simple guard like if (timer) return; keeps your stopwatch honest. Professional code is full of small guards like this.
State + display = an app
Your stopwatch splits cleanly into state (the elapsed variable holding the truth) and display (the #display element showing it). Every tick updates state first, then renders it into the DOM with textContent. Reset means: set state back to zero, render again. This state-then-render pattern is the architecture behind almost every interface — game loops redraw the world from game state, and frameworks like React exist purely to keep state and screen in sync. You are building the same idea with your bare hands.