JavaScript Timers
JavaScript provides several timing functions to execute code after delays or at regular intervals.
setTimeout
javascript// Basic setTimeout setTimeout(() => { console.log('This runs after 1 second'); }, 1000); // With parameters setTimeout((name, age) => { console.log(`Hello ${name}, you are ${age} years old`); }, 2000, 'John', 25); // Store timer ID for cancellation const timerId = setTimeout(() => { console.log('This might not run'); }, 3000); // Cancel the timer clearTimeout(timerId); // Minimum delay is ~4ms in browsers setTimeout(() => console.log('Immediate'), 0); // Actually ~4ms
setInterval
javascript// Basic setInterval const intervalId = setInterval(() => { console.log('This runs every 2 seconds'); }, 2000); // Stop after 10 seconds setTimeout(() => { clearInterval(intervalId); console.log('Interval stopped'); }, 10000); // Counter example let count = 0; const counter = setInterval(() => { count++; console.log(`Count: ${count}`); if (count >= 5) { clearInterval(counter); console.log('Counter finished'); } }, 1000);
Advanced Timer Patterns
javascript// Recursive setTimeout (preferred over setInterval) function recursiveTimer(callback, delay, maxRuns = Infinity) { let runs = 0; function run() { if (runs < maxRuns) { callback(runs); runs++; setTimeout(run, delay); } } run(); } recursiveTimer((run) => { console.log(`Run #${run + 1}`); }, 1000, 5); // Dynamic delay function dynamicTimer(callback, getDelay) { function run() { callback(); const delay = getDelay(); if (delay > 0) { setTimeout(run, delay); } } run(); } let delayCount = 0; dynamicTimer( () => console.log('Dynamic timer tick'), () => { delayCount++; return delayCount < 5 ? delayCount * 500 : 0; // Increasing delays } );
Timer Utilities
javascript// Delay utility (Promise-based) function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // Usage with async/await async function example() { console.log('Start'); await delay(1000); console.log('After 1 second'); await delay(2000); console.log('After 3 seconds total'); } // Timeout wrapper for promises function withTimeout(promise, ms) { const timeout = new Promise((_, reject) => { setTimeout(() => reject(new Error('Timeout')), ms); }); return Promise.race([promise, timeout]); } // Usage async function fetchWithTimeout() { try { const result = await withTimeout(fetch('/api/data'), 5000); console.log('Data fetched:', result); } catch (error) { console.error('Request timed out or failed:', error.message); } } // Timer manager class class TimerManager { constructor() { this.timers = new Map(); } setTimeout(callback, delay, id = Symbol()) { const timerId = setTimeout(() => { callback(); this.timers.delete(id); }, delay); this.timers.set(id, { type: 'timeout', id: timerId }); return id; } setInterval(callback, delay, id = Symbol()) { const timerId = setInterval(callback, delay); this.timers.set(id, { type: 'interval', id: timerId }); return id; } clear(id) { const timer = this.timers.get(id); if (timer) { if (timer.type === 'timeout') { clearTimeout(timer.id); } else { clearInterval(timer.id); } this.timers.delete(id); } } clearAll() { this.timers.forEach((timer, id) => { this.clear(id); }); } } const timerManager = new TimerManager(); const id1 = timerManager.setTimeout(() => console.log('Timer 1'), 1000); const id2 = timerManager.setInterval(() => console.log('Timer 2'), 500); // Clear specific timer // timerManager.clear(id1); // Clear all timers // timerManager.clearAll();
Practical Examples
javascript// Countdown timer function createCountdown(seconds, callback) { let remaining = seconds; const timer = setInterval(() => { console.log(`Time remaining: ${remaining} seconds`); remaining--; if (remaining < 0) { clearInterval(timer); console.log('Time\'s up!'); if (callback) callback(); } }, 1000); return timer; } // Auto-save functionality function setupAutoSave(saveFunction, intervalMs = 30000) { let hasChanges = false; let saveTimer; function markChanged() { hasChanges = true; if (!saveTimer) { saveTimer = setInterval(() => { if (hasChanges) { saveFunction(); hasChanges = false; } }, intervalMs); } } function stopAutoSave() { if (saveTimer) { clearInterval(saveTimer); saveTimer = null; } } return { markChanged, stopAutoSave }; } // Usage const autoSave = setupAutoSave(() => { console.log('Auto-saving document...'); }); // Simulate changes // autoSave.markChanged(); // Polling with exponential backoff function pollWithBackoff(checkFunction, maxAttempts = 10) { let attempts = 0; function poll() { attempts++; if (checkFunction()) { console.log('Condition met!'); return; } if (attempts >= maxAttempts) { console.log('Max attempts reached'); return; } const delay = Math.min(1000 * Math.pow(2, attempts - 1), 30000); console.log(`Attempt ${attempts} failed, retrying in ${delay}ms`); setTimeout(poll, delay); } poll(); } // Usage let condition = false; setTimeout(() => condition = true, 5000); // Condition becomes true after 5s pollWithBackoff(() => condition); // Animation frame timing (for smooth animations) function animateWithTimer(duration, callback) { const start = performance.now(); function frame(currentTime) { const elapsed = currentTime - start; const progress = Math.min(elapsed / duration, 1); callback(progress); if (progress < 1) { requestAnimationFrame(frame); } } requestAnimationFrame(frame); } // Usage animateWithTimer(2000, (progress) => { const element = document.getElementById('animated-element'); if (element) { element.style.transform = `translateX(${progress * 200}px)`; } });