JavaScript has no built-in clearAllTimeout(). To cancel several timeouts at once, keep their IDs and call clearTimeout() on each one. This guide gives you a small timer group that does that for you, shows the browser-only trick that clears every timer on a page (and why it's risky), and covers intervals, React, debouncing and Node.js.
Tested with: Chromium 156 and WebKit 27.2 (Safari's engine) via Playwright, Node.js 20.20 and React 19.3, October 2026.
clearTimeout Basics
setTimeout() returns an ID. Pass that ID to clearTimeout() to cancel the callback before it runs:
const timeoutId = setTimeout(() => {
console.log("This never runs");
}, 2000);
clearTimeout(timeoutId); // cancel it before the 2 seconds are up- Browsers return a number (typeof id === "number"); Node.js returns a Timeout object. Treat the ID as opaque and just pass it back.
- Clearing is always safe: clearTimeout(undefined), an ID that already ran, or any other bad value does nothing and doesn't throw. In our tests none of them threw.
- clearTimeout and clearInterval share the same IDs. In our tests clearTimeout() stopped an interval and clearInterval() cancelled a timeout, in Chromium, WebKit and Node.js. Use the matching one anyway, so the code says what it means.
See MDN for setTimeout and clearTimeout.
How to Clear All Your Timeouts at Once
Wrap setTimeout and setInterval so every ID goes into a Set, and remove each timeout's ID once it has run:
// A group of timers you can cancel together. Works in browsers and Node.js.
export function createTimerGroup() {
const timeouts = new Set();
const intervals = new Set();
return {
setTimeout(callback, delay, ...args) {
const id = setTimeout(() => {
timeouts.delete(id); // forget it once it has run
callback(...args);
}, delay);
timeouts.add(id);
return id;
},
setInterval(callback, delay, ...args) {
const id = setInterval(callback, delay, ...args);
intervals.add(id);
return id;
},
clear(id) {
clearTimeout(id);
clearInterval(id);
timeouts.delete(id);
intervals.delete(id);
},
clearAll() {
timeouts.forEach((id) => clearTimeout(id));
intervals.forEach((id) => clearInterval(id));
timeouts.clear();
intervals.clear();
},
get size() {
return timeouts.size + intervals.size;
},
};
}import { createTimerGroup } from "./timer-group.js";
const timers = createTimerGroup();
timers.setTimeout(() => showHint("Need help?"), 5000);
timers.setTimeout(() => autosave(), 30000);
timers.setInterval(() => refreshClock(), 1000);
// Later, e.g. when the user leaves the page or closes a dialog:
timers.clearAll();
console.log(timers.size); // 0- A Set, not an array: deleting a finished ID is instant, and the same ID can't be stored twice.
- Finished timeouts are forgotten. Many examples push IDs into an array and never remove them. In our test, an array like that still held 5 IDs after all 5 timeouts had run; the group's size was 0.
- One group per feature: a dialog, a game level or a component can each have its own group, so clearing one doesn't touch the others.
In our tests, clearAll() stopped five pending timeouts and an interval before any of them ran, and clear(id) cancelled just one timeout while the other still ran.
Why not a global array?
let timeoutIds = [];
for (let i = 0; i < 5; i++) {
timeoutIds.push(setTimeout(() => {}, 1000));
}
// After all five have run, timeoutIds.length is still 5.
// In a long-running page this array only ever grows.A global let timeoutIds also breaks easily: an earlier version of this article declared it in two snippets, and running both together throws SyntaxError: Identifier 'timeoutIds' has already been declared. A group created with a function avoids both problems.
Clearing Every Timer on the Page (Browser Only)
If you need to stop timers you didn't create yourself, for example while debugging or in a test, there's a well-known loop:
// Browser only: cancels EVERY pending timeout and interval on the page,
// including ones created by libraries, analytics and ads. Use with care.
export function clearEveryTimer() {
// Browsers hand out timer IDs as increasing numbers, so a new timer's ID
// is higher than every pending one.
const highestId = setTimeout(() => {}, 0);
for (let id = highestId; id > 0; id--) {
clearTimeout(id);
}
}It relies on browsers giving out timer IDs as increasing numbers, so it clears every ID from the newest one down to 1. In Chromium and WebKit it stopped two timeouts and an interval that it had no reference to. But be careful:
- It cancels everyone's timers, including your framework's, analytics and ads. While testing this article, it also cancelled the timers our own React test was waiting on, so that test never finished.
- It doesn't work in Node.js, where IDs are objects, not numbers. In our Node.js test, every callback still ran.
Use it for debugging, tests or a bookmarklet, not in production code. For your own timers, use a timer group.
Clearing Timeouts in React
A timeout that runs after a component unmounts can update state that no longer exists, or close something twice. This hook gives each component its own group and clears it on unmount:
// useTimeouts.jsx
import { useEffect, useRef } from "react";
import { createTimerGroup } from "./timer-group";
// One timer group per component; everything is cleared on unmount.
export function useTimeouts() {
const groupRef = useRef(null);
if (!groupRef.current) groupRef.current = createTimerGroup();
useEffect(() => {
const group = groupRef.current;
return () => group.clearAll();
}, []);
return groupRef.current;
}
// Usage
export function Toast({ message, onClose }) {
const timers = useTimeouts();
useEffect(() => {
timers.setTimeout(onClose, 3000); // auto-close after 3 s
}, [timers, onClose]);
return (
<div role="status">
{message}
<button onClick={() => { timers.clearAll(); onClose(); }}>Close</button>
</div>
);
}- The group is created once per component (useRef) and cleared in the effect's cleanup.
- In our React 19.3 test under StrictMode (which mounts, unmounts and remounts effects in development), a timeout set in an effect still ran once while mounted and never ran after unmount. The Toast's Close button cleared its auto-close timer.
- Pass a stable onClose (for example wrapped in useCallback); a new function on every render re-runs the effect and schedules another timeout.
For a single timeout, a plain cleanup is enough: useEffect(() => { const id = setTimeout(fn, 1000); return () => clearTimeout(id); }, []). If you see effects running twice in development, read our guide to useEffect running twice.
Debounce: Cancel the Previous Timeout
Often you don't want to clear all timeouts, only the previous one, so an action runs once after the user stops typing or clicking:
// Run `fn` only after calls have stopped for `delay` ms.
export function debounce(fn, delay) {
let timeoutId;
function debounced(...args) {
clearTimeout(timeoutId); // cancel the previous pending call
timeoutId = setTimeout(() => fn.apply(this, args), delay);
}
debounced.cancel = () => clearTimeout(timeoutId);
return debounced;
}
// Example: save a draft 500 ms after the user stops typing
const saveDraft = debounce((text) => console.log("Saving:", text), 500);
textarea.addEventListener("input", (e) => saveDraft(e.target.value));In our test, four quick calls produced a single run with the last value, and cancel() stopped a pending call. This is the pattern behind search-as-you-type; see it in our dynamic search bar guide.
setTimeout vs setInterval
| setTimeout | setInterval | |
|---|---|---|
| Runs | Once, after the delay | Repeatedly, every delay |
| Cancel with | clearTimeout(id) | clearInterval(id) |
| Good for | Delays, debouncing, polling after each request | Clocks, simple animations, fixed ticks |
| Watch out for | Forgetting to cancel on unmount | Slow callbacks overlapping; runs forever until cleared |
const intervalId = setInterval(tick, 1000);
clearInterval(intervalId);
// Repeating async work: schedule the next run only after this one finishes,
// so slow requests never overlap.
let pollId;
let polling = true;
async function poll() {
await refreshData();
if (polling) pollId = setTimeout(poll, 5000);
}
poll();
function stopPolling() {
polling = false; // a request in flight won't schedule another run
clearTimeout(pollId); // and a scheduled run is cancelled
}The polling flag matters: in our test, calling only clearTimeout(pollId) while a request was still running didn't stop the loop, because the request finished afterwards and scheduled a new timeout. Browsers also slow down timers in background tabs; see our guide to detecting tab changes if you want to pause work when the page is hidden.
Cancelling Timers in Node.js
Node.js has a promise-based setTimeout that accepts an AbortSignal, so one abort() cancels every timer that shares the signal:
import { setTimeout as sleep } from "node:timers/promises";
const controller = new AbortController();
sleep(5000, "done", { signal: controller.signal })
.then((value) => console.log(value))
.catch((err) => {
if (err.name === "AbortError") console.log("Timer cancelled");
else throw err;
});
controller.abort(); // cancels every timer that uses this signalIn our test this printed "Timer cancelled" and the script exited in about 130 ms instead of waiting 5 seconds. With the classic API, clearTimeout(timeout) works as in the browser, and timeout.unref() lets the process exit even if the timer is still pending. See the Node.js timers docs.
Common Mistakes
| Mistake | What happens | Fix |
|---|---|---|
| Not saving the ID from setTimeout | You can't cancel it later | const id = setTimeout(…) |
| Pushing IDs into an array and never removing them | The array grows forever | Use a Set and delete IDs when they run |
| No cleanup in React effects | Callbacks run after unmount | Return () => clearTimeout(id) |
| Using the clear-every-timer loop in production | Breaks libraries, ads and frameworks | Track and clear only your own timers |
| setInterval for slow async work | Requests overlap and pile up | Schedule the next setTimeout after each run |
| Passing a string: setTimeout("fn()", 100) | Runs eval-like code; blocked by strict CSP | Pass a function |
FAQs
Is there a clearAllTimeout() function in JavaScript?
No. Neither browsers nor Node.js have one. Keep your timer IDs (the timer group above does it for you) and clear them in a loop.
How do I clear all timeouts in JavaScript?
For your own timers, store the IDs and call clearTimeout() on each, or use createTimerGroup().clearAll(). To clear every timer on a page, including other scripts', loop from a new timer's ID down to 1 calling clearTimeout, but only for debugging.
Does clearTimeout work on setInterval?
Yes. Timeouts and intervals share one pool of IDs, so clearTimeout() stops an interval and clearInterval() cancels a timeout. Using the matching function is clearer.
What does setTimeout return?
A positive integer in browsers and a Timeout object in Node.js. Either way, it's the value you pass to clearTimeout.
What happens if I call clearTimeout after the timeout has run?
Nothing. It's safe to call, which is why cleanup functions can always clear without checking first.
How do I clear a timeout in React?
Return a cleanup function from useEffect that calls clearTimeout(id), or use the useTimeouts hook above for several timers.
Related Articles
View allAbout Muhaymin Bin Mehmood
Front-end Developer skilled in the MERN stack, experienced in web and mobile development. Proficient in React.js, Node.js, and Express.js, with a focus on client interactions, sales support, and high-performance applications.




