Timers in JavaScript
JavaScript provides built-in timer functions that allow you to execute code asynchronously after a specified delay or at regular intervals. The two primary timer functions are setTimeout() and setInterval().
Despite JavaScript being a single-threaded language, timers enable asynchronous, non-blocking execution by leveraging the browser's Web APIs (or Node.js's underlying libuv C++ library) and the Event Loop.
1. setTimeout()
The setTimeout() function executes a specified block of code or function once after a given delay (in milliseconds).
Syntax
const timerId = setTimeout(callback, delay, arg1, arg2, ...);
- callback: The function to be executed.
- delay: The time (in ms) to wait before execution. Default is 0.
- args: Optional arguments passed to the callback function.
Example
console.log("Start");
setTimeout(() => {
console.log("Executed after 2 seconds");
}, 2000);
console.log("End");
// Output:
// Start
// End
// Executed after 2 seconds
2. setInterval()
The setInterval() function executes a specified block of code or function repeatedly, with a fixed time delay between each call.
Syntax
const intervalId = setInterval(callback, delay, arg1, arg2, ...);
Example
let count = 0;
const intervalId = setInterval(() => {
count++;
console.log(`Interval count: ${count}`);
if (count === 3) {
clearInterval(intervalId); // Stops the interval after 3 executions
}
}, 1000);
3. Canceling Timers
Both setTimeout and setInterval return a unique identifier (usually a number in browsers, or a Timer object in Node.js). You can use these identifiers to cancel the timer before it executes.
clearTimeout(timerId): Cancels a pendingsetTimeout.clearInterval(intervalId): Cancels a runningsetInterval.
const id = setTimeout(() => {
console.log("This will never run!");
}, 5000);
clearTimeout(id); // Timer is canceled immediately
4. The "Zero Delay" Trick
Sometimes you will see setTimeout called with a delay of 0 milliseconds.
console.log("1");
setTimeout(() => console.log("2"), 0);
console.log("3");
Output:
1
3
2
Why does "2" print last?
Even with a 0ms delay, setTimeout pushes the callback to the Macrotask Queue (or Callback Queue). The Event Loop will only pick up tasks from this queue after the main call stack is entirely empty. Thus, synchronous code will always finish executing before any setTimeout callback, even if the delay is zero.
5. Potential Pitfalls
this Binding
When passing object methods as callbacks, they lose their this binding.
const user = {
name: "Alice",
greet() {
console.log(this.name);
}
};
// `this` inside greet will be undefined/window
setTimeout(user.greet, 1000);
// Fix using arrow function or bind:
setTimeout(() => user.greet(), 1000);
setTimeout(user.greet.bind(user), 1000);
Inaccurate Delays
Timers in JavaScript are not guaranteed to execute at the exact millisecond. The delay argument specifies the minimum delay. If the main thread is blocked by a heavy synchronous task, the timer callback will have to wait in the queue until the call stack clears.