Timers in JavaScript
Introduction
Timers schedule code to run later or repeatedly: setTimeout, setInterval, and their cancel functions. They are asynchronous—your script continues while waiting. Timers appear in UI debouncing, polling, and animation ticks in browsers and in Node background tasks.
Prerequisites
setTimeout — Run Once Later
// Run after ~1000 ms
const id = setTimeout(() => {
console.log("delayed message");
}, 1000);
console.log("scheduled", id);Cancel before it fires:
// clearTimeout prevents callback
const handle = setTimeout(() => console.log("never"), 5000);
clearTimeout(handle);
console.log("cancelled");Delay is a minimum—busy main threads can delay longer.
setInterval — Run Repeatedly
// Every 500 ms until cleared
let count = 0;
const intervalId = setInterval(() => {
count += 1;
console.log("tick", count);
if (count >= 3) clearInterval(intervalId);
}, 500);Always store the id if you need to stop later.
Passing Arguments (Legacy Pattern)
// Prefer arrow wrapper in modern code
setTimeout(
(name) => console.log("hi", name),
200,
"Ada"
);Modern style:
setTimeout(() => console.log("hi", "Ada"), 200);Timers and the Event Loop
Timer callbacks run on the macrotask queue after current synchronous code finishes—order matters with other async work (covered with Promises).
requestAnimationFrame (Browser)
For smooth visuals, browsers use requestAnimationFrame instead of tight setInterval loops—not a timer API but related scheduling.
Mini Example: Debounce Search Input
// Only run search after user stops typing 300ms
let debounceTimer;
function onSearchInput(query) {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
console.log("search:", query);
}, 300);
}
onSearchInput("j");
onSearchInput("ja");
onSearchInput("jav");FAQ
Are delays exact?
No—minimum delay only; tab throttling in background browsers adds more skew.
setInterval drift?
Repeated work longer than the interval stacks delays—consider recursive setTimeout for fixed gaps between completions.
Node process exit?
Pending timers keep Node alive unless you clearTimeout or call process.exit.