clearInterval()
Stops a repeating timer started by setInterval() so its callback no longer runs.
clearInterval(intervalID)- Added in JavaScript Baseline widely available since July 2015
Parameters
| Parameter | Type | Description |
|---|---|---|
$intervalID | number | The identifier returned by the corresponding setInterval() call. If it does not identify an active repeated action, the call does nothing. |
Return value
undefinedNothing.
clearInterval() is the only thing that stops a setInterval() timer. Until it is called with the right ID, the callback keeps firing for the lifetime of the page or worker — an interval has no built-in run limit and no completion state. Like its timeout counterpart it is a forgiving no-op: an unknown ID, an already-cleared ID, or undefined all pass silently, and it returns nothing.
When to reach for it
Every setInterval() needs a matching stop condition. Typical ones are a counter that reaches zero, a poll that finally sees the value it wanted, a poll that has given up after N attempts, or a component or view being torn down. Clearing on teardown is the one people forget, and it is the one that causes callbacks to keep touching state that no longer exists.
What trips people up
The ID is your only handle on the timer. Reassign the variable that holds it, or start a second interval on top of the first, and the original becomes unstoppable for the rest of the session — a classic leak that shows up as a page getting steadily busier. If you start intervals in a loop, collect the IDs in an array and clear all of them. Clearing from inside the callback is fine, because the callback cannot run until the assignment that stores the ID has completed.
Example
When to use it
- Stopping a poller as soon as the value it is waiting for arrives
- Giving a poll a maximum attempt count so it cannot spin forever
- Clearing every timer a component started when it is unmounted
- Ending a countdown or animation loop when it reaches its final frame
Frequently asked questions
Why does my setInterval keep running after I call clearInterval?
Almost always because you cleared a different ID than the one that is running — the variable was reassigned, the interval was started twice, or the clear happened in a scope holding a stale copy. There is no API to list active timers, so log the ID at creation and at clearing to confirm they match.
Does clearInterval throw if the ID is wrong?
No. Passing an unknown ID, undefined, or an ID that was already cleared does nothing at all and returns undefined, so the call is safe to make unconditionally in cleanup code.
Can I use clearInterval on a setTimeout?
Yes, since both functions draw IDs from a single shared pool, so either clear function will cancel either kind of timer. It works, but pairing clearTimeout with setTimeout and clearInterval with setInterval keeps the code's intent obvious.
More examples
Polling with a give-up limit
Two exit paths both call clearInterval, so the timer cannot outlive its purpose. The attempt ceiling is the important half: without it, a condition that never becomes true leaves the interval polling forever.
let ready = false;
setTimeout(() => { ready = true; }, 40);
let attempts = 0;
const poll = setInterval(() => {
attempts += 1;
if (ready) {
clearInterval(poll);
console.log(`ready after ${attempts} polls`);
} else if (attempts >= 20) {
clearInterval(poll);
console.log("gave up after 20 polls");
}
}, 10);
await new Promise((r) => setTimeout(r, 150));Track every ID so nothing is orphaned
Three intervals started in a loop each need their own clearInterval call, so the IDs are collected in an array. Keeping only the last ID in a single variable would leave the first two running with no way to reach them.
const ids = [];
for (const name of ["alpha", "beta", "gamma"]) {
ids.push(setInterval(() => console.log(`${name} tick`), 20));
}
await new Promise((r) => setTimeout(r, 50));
for (const id of ids) clearInterval(id);
console.log(`stopped ${ids.length} intervals`);
await new Promise((r) => setTimeout(r, 50));
console.log("no further ticks above this line");Clearing from inside the callback
Referencing id inside its own callback is safe because the callback cannot run until the current synchronous block finishes, by which time the const is initialised. The same code with a delay of 0 behaves identically.
let frame = 0;
const id = setInterval(() => {
frame += 1;
console.log("frame", frame);
if (frame === 4) clearInterval(id); // `id` is already assigned
}, 15);
console.log("id assigned before any tick:", typeof id !== "undefined");
await new Promise((r) => setTimeout(r, 200));
console.log("stopped at frame", frame);
Discussion