Timers in JavaScript
JavaScript provides timing functions that allow you to execute code after a delay or at regular intervals. These functions are essential for creating animations, scheduling tasks, and managing asynchronous operations.
setTimeout()
The setTimeout() function executes a piece of code or a function once after a specified delay (in milliseconds).
Basic Syntax
setTimeout(function, delay, arg1, arg2, ...)- function: The function to execute
- delay: Time to wait before execution (in milliseconds)
- arg1, arg2, …: Optional arguments to pass to the function
Simple Example
console.log("Start");
setTimeout(function() { console.log("This runs after 2 seconds");}, 2000);
console.log("End");
// Output:// Start// End// This runs after 2 seconds (after 2-second delay)With Arrow Function
setTimeout(() => { console.log("Hello after 1 second!");}, 1000);Passing Arguments
function greet(name, greeting) { console.log(`${greeting}, ${name}!`);}
setTimeout(greet, 1500, "Alice", "Hello");// Output after 1.5 seconds: Hello, Alice!Using a Reference
function showMessage() { console.log("Message displayed!");}
// Pass function reference (without parentheses)setTimeout(showMessage, 1000);clearTimeout()
The clearTimeout() function cancels a timeout that was previously set with setTimeout().
const timeoutId = setTimeout(() => { console.log("This will never run");}, 3000);
// Cancel the timeoutclearTimeout(timeoutId);console.log("Timeout cancelled");Practical Example: Cancellable Delay
let timeoutId;
function showNotification(message) { console.log(message);}
function scheduleNotification(message, delay) { // Clear any existing timeout if (timeoutId) { clearTimeout(timeoutId); }
timeoutId = setTimeout(() => { showNotification(message); }, delay);}
scheduleNotification("First message", 2000);scheduleNotification("Second message", 1000); // Cancels first, shows this one
// Output after 1 second: Second messagesetInterval()
The setInterval() function repeatedly executes code at a specified interval.
Basic Syntax
setInterval(function, interval, arg1, arg2, ...)- function: The function to execute repeatedly
- interval: Time between executions (in milliseconds)
Simple Example
let count = 0;
const intervalId = setInterval(() => { count++; console.log(`Count: ${count}`);}, 1000);
// Output every second:// Count: 1// Count: 2// Count: 3// ... (continues indefinitely)Countdown Timer
let timeLeft = 10;
const countdown = setInterval(() => { console.log(timeLeft); timeLeft--;
if (timeLeft < 0) { clearInterval(countdown); console.log("Time's up!"); }}, 1000);
// Output:// 10// 9// 8// ... (down to 0)// Time's up!clearInterval()
The clearInterval() function stops an interval that was set with setInterval().
let count = 0;
const intervalId = setInterval(() => { count++; console.log(count);
if (count === 5) { clearInterval(intervalId); console.log("Interval stopped"); }}, 1000);
// Output:// 1// 2// 3// 4// 5// Interval stoppedReal-World Examples
1. Debounce Function
Delays execution until after the user stops performing an action.
function debounce(func, delay) { let timeoutId;
return function(...args) { // Clear the previous timeout clearTimeout(timeoutId);
// Set a new timeout timeoutId = setTimeout(() => { func.apply(this, args); }, delay); };}
// Usage: Search as user typesconst searchInput = document.querySelector("#search");
const performSearch = debounce((event) => { console.log("Searching for:", event.target.value); // API call would go here}, 500);
searchInput.addEventListener("input", performSearch);// Search only happens 500ms after user stops typing2. Digital Clock
function updateClock() { const now = new Date(); const hours = String(now.getHours()).padStart(2, '0'); const minutes = String(now.getMinutes()).padStart(2, '0'); const seconds = String(now.getSeconds()).padStart(2, '0');
const timeString = `${hours}:${minutes}:${seconds}`; console.log(timeString);
// Update DOM element // document.querySelector("#clock").textContent = timeString;}
// Update every secondsetInterval(updateClock, 1000);updateClock(); // Initial call to show immediately3. Auto-Save Feature
class TextEditor { constructor() { this.content = ""; this.saveTimeoutId = null; }
updateContent(newContent) { this.content = newContent; this.scheduleSave(); }
scheduleSave() { // Clear previous save timer if (this.saveTimeoutId) { clearTimeout(this.saveTimeoutId); }
// Schedule new save after 2 seconds of inactivity this.saveTimeoutId = setTimeout(() => { this.save(); }, 2000); }
save() { console.log("Auto-saving content:", this.content); // Actual save logic here }}
const editor = new TextEditor();editor.updateContent("Hello");editor.updateContent("Hello World"); // Previous save cancelled// Saves "Hello World" after 2 seconds of no changes4. Polling for Updates
function pollForUpdates() { console.log("Checking for updates...");
// Simulate API call fetch("/api/updates") .then(response => response.json()) .then(data => { console.log("Update received:", data); }) .catch(error => { console.error("Error fetching updates:", error); });}
// Poll every 5 secondsconst pollingInterval = setInterval(pollForUpdates, 5000);
// Stop polling after 1 minutesetTimeout(() => { clearInterval(pollingInterval); console.log("Stopped polling");}, 60000);5. Animation Loop
let position = 0;const element = document.querySelector("#box");
const animationInterval = setInterval(() => { position += 5; element.style.left = position + "px";
// Stop when element reaches 300px if (position >= 300) { clearInterval(animationInterval); }}, 50); // Update every 50ms for smooth animation6. Notification System
class NotificationManager { constructor() { this.notifications = []; }
show(message, duration = 3000) { const notification = { id: Date.now(), message: message };
this.notifications.push(notification); console.log(`📢 ${message}`);
// Auto-remove after duration setTimeout(() => { this.remove(notification.id); }, duration); }
remove(id) { this.notifications = this.notifications.filter(n => n.id !== id); console.log("Notification removed"); }}
const notifier = new NotificationManager();notifier.show("Welcome!", 2000);notifier.show("You have 3 new messages", 5000);setTimeout vs setInterval
setTimeout for Repeated Execution
// Using setTimeout recursivelyfunction repeatWithTimeout() { console.log("Repeating task");
setTimeout(repeatWithTimeout, 1000);}
repeatWithTimeout();Advantages:
- Guarantees delay between executions
- Can conditionally stop or change interval
- More control over execution flow
setInterval Example
// Using setIntervalconst intervalId = setInterval(() => { console.log("Repeating task");}, 1000);
// Must manually stop// clearInterval(intervalId);Use setInterval when:
- You need simple, consistent intervals
- The task duration is predictable and short
Use recursive setTimeout when:
- Task duration varies
- You need guaranteed delay between executions
- You want more control over the loop
Common Pitfalls
1. Minimum Delay
// Browsers enforce minimum delays (usually 4ms)setTimeout(() => { console.log("This won't run instantly");}, 0);
console.log("This runs first");
// Output:// This runs first// This won't run instantly2. this Context
const obj = { name: "Test", greet: function() { setTimeout(function() { console.log(this.name); // undefined - lost context }, 1000);
// Solution: Use arrow function setTimeout(() => { console.log(this.name); // Test - preserved context }, 1000); }};3. Memory Leaks
// Bad: Creates memory leak if not clearedfunction startTimer() { setInterval(() => { console.log("Running..."); }, 1000);}
// Good: Store reference and clear when donelet timerId;
function startTimer() { timerId = setInterval(() => { console.log("Running..."); }, 1000);}
function stopTimer() { if (timerId) { clearInterval(timerId); timerId = null; }}4. Loop Variables
// Wrong: All timeouts log 5for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); // 5, 5, 5, 5, 5 }, 1000);}
// Solution 1: Use let (block scope)for (let i = 0; i < 5; i++) { setTimeout(function() { console.log(i); // 0, 1, 2, 3, 4 }, 1000);}
// Solution 2: Use IIFEfor (var i = 0; i < 5; i++) { (function(index) { setTimeout(function() { console.log(index); // 0, 1, 2, 3, 4 }, 1000); })(i);}Best Practices
-
Always store timer IDs for cleanup
const timerId = setTimeout(() => {}, 1000);// Store timerId for later cleanup -
Clear timers when no longer needed
// In ReactuseEffect(() => {const timer = setInterval(() => {}, 1000);return () => clearInterval(timer); // Cleanup}, []); -
Use arrow functions to preserve
thissetTimeout(() => {this.doSomething();}, 1000); -
Consider using
requestAnimationFramefor animations// Better for animations than setIntervalfunction animate() {// Animation logicrequestAnimationFrame(animate);}animate();
Summary
- setTimeout() executes code once after a delay
- setInterval() executes code repeatedly at intervals
- clearTimeout() and clearInterval() cancel timers
- Delays are in milliseconds (1000ms = 1 second)
- Always store timer IDs for proper cleanup
- Use arrow functions to preserve
thiscontext - Be aware of minimum delay enforcement in browsers
- Clear timers to prevent memory leaks