timers
The timers module provides functions for scheduling code execution after a certain period of time. It includes both callback-based and promise-based APIs.
Import
// Timer functions are available globally
// or import explicitly:
const { setTimeout, setInterval, setImmediate, clearTimeout, clearInterval, clearImmediate } = require('timers');
// For promise-based API:
const { setTimeout: setTimeoutPromise, setImmediate: setImmediatePromise, setInterval: setIntervalPromise } = require('timers/promises');
API Reference
setTimeout(callback, delay[, ...args])
Schedules execution of a one-time callback after delay milliseconds.
Parameters:
callback- Function to executedelay- Delay in milliseconds (minimum 1ms)...args- Additional arguments to pass to the callback
Returns: A Timeout object
clearTimeout(timeout)
Cancels a Timeout object created by setTimeout().
setInterval(callback, delay[, ...args])
Schedules repeated execution of callback every delay milliseconds.
Returns: A Timeout object
clearInterval(timeout)
Cancels a Timeout object created by setInterval().
setImmediate(callback[, ...args])
Schedules immediate execution of callback after I/O events callbacks.
Returns: An Immediate object
clearImmediate(immediate)
Cancels an Immediate object created by setImmediate().
Promises API
timers/promises.setTimeout(delay[, value[, options]])
Returns a Promise that resolves after delay milliseconds.
timers/promises.setImmediate([value[, options]])
Returns a Promise that resolves after the current event loop iteration.
timers/promises.setInterval(delay[, value[, options]])
Returns an async iterator that generates values every delay milliseconds.
Examples
Basic setTimeout
export async function handler(event) {
console.log('Start');
// Schedule callback after 1 second
setTimeout(() => {
console.log('Executed after 1 second');
}, 1000);
// Use await to wait for completion
await new Promise(resolve => setTimeout(resolve, 1100));
console.log('End');
return { message: 'Timer completed' };
}
setTimeout with Arguments
export async function handler(event) {
function greet(name, message) {
console.log(`${message}, ${name}!`);
}
// Pass arguments to callback
setTimeout(greet, 100, 'Alice', 'Hello');
setTimeout(greet, 200, 'Bob', 'Hi');
// Wait for timers
await new Promise(resolve => setTimeout(resolve, 300));
return { message: 'Greetings sent' };
}
Clearing Timeouts
export async function handler(event) {
const results = [];
// Schedule timer
const timer = setTimeout(() => {
results.push('This should not execute');
}, 100);
// Cancel before it fires
clearTimeout(timer);
// Wait to ensure it was cancelled
await new Promise(resolve => setTimeout(resolve, 200));
results.push('Timer was cancelled');
return { results };
}
Using setInterval
export async function handler(event) {
const results = [];
let count = 0;
// Repeat every 100ms
const interval = setInterval(() => {
count++;
results.push(`Tick ${count}`);
// Stop after 5 ticks
if (count >= 5) {
clearInterval(interval);
}
}, 100);
// Wait for interval to complete
await new Promise(resolve => setTimeout(resolve, 600));
return { results, count };
}
Using setImmediate
export async function handler(event) {
const operations = [];
operations.push('1. Synchronous');
// Execute after I/O events
setImmediate(() => {
operations.push('3. Immediate');
});
// Execute in next event loop tick
setTimeout(() => {
operations.push('4. Timeout');
}, 0);
operations.push('2. Synchronous');
// Wait for async operations
await new Promise(resolve => setTimeout(resolve, 10));
return { operations };
}
Promise-based setTimeout
const { setTimeout } = require('timers/promises');
export async function handler(event) {
console.log('Start');
// Wait 1 second using promises
await setTimeout(1000);
console.log('After 1 second');
// Wait and return a value
const result = await setTimeout(500, 'Done waiting');
console.log(result); // 'Done waiting'
return { message: 'Completed' };
}
Promise-based setImmediate
const { setImmediate } = require('timers/promises');
export async function handler(event) {
console.log('Start');
// Yield to event loop
await setImmediate();
console.log('After immediate');
// Return a value
const value = await setImmediate('Result');
return { value };
}
Promise-based setInterval
const { setInterval } = require('timers/promises');
export async function handler(event) {
const results = [];
let count = 0;
// Create async iterator
const interval = setInterval(100);
// Iterate over intervals
for await (const timestamp of interval) {
count++;
results.push(`Tick ${count} at ${timestamp}`);
// Stop after 5 iterations
if (count >= 5) {
break;
}
}
return { results, count };
}
Aborting Promise-based Timers
const { setTimeout } = require('timers/promises');
export async function handler(event) {
const controller = new AbortController();
const { signal } = controller;
// Abort after 500ms
setTimeout(500).then(() => {
controller.abort();
});
try {
// This will be aborted
await setTimeout(1000, undefined, { signal });
return { message: 'Completed' };
} catch (error) {
if (error.name === 'AbortError') {
return { message: 'Timer was aborted' };
}
throw error;
}
}
Delayed Function Execution
export async function handler(event) {
function executeTask(taskId, delay) {
return new Promise(resolve => {
setTimeout(() => {
console.log(`Task ${taskId} executed`);
resolve({ taskId, completedAt: Date.now() });
}, delay);
});
}
// Execute tasks with different delays
const results = await Promise.all([
executeTask(1, 100),
executeTask(2, 200),
executeTask(3, 50)
]);
return { results };
}
Polling with setInterval
export async function handler(event) {
let attempts = 0;
const maxAttempts = 10;
// Simulate checking for a condition
function checkCondition() {
attempts++;
const ready = Math.random() > 0.7; // 30% chance
console.log(`Attempt ${attempts}: ${ready ? 'Ready!' : 'Not ready'}`);
return ready;
}
return new Promise((resolve, reject) => {
const interval = setInterval(() => {
if (checkCondition()) {
clearInterval(interval);
resolve({
success: true,
attempts
});
} else if (attempts >= maxAttempts) {
clearInterval(interval);
reject(new Error('Max attempts reached'));
}
}, 100);
});
}
Debouncing with Timers
export async function handler(event) {
function debounce(func, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
return new Promise(resolve => {
timeoutId = setTimeout(() => {
resolve(func(...args));
}, delay);
});
};
}
// Function to debounce
function processInput(input) {
console.log('Processing:', input);
return { processed: input.toUpperCase() };
}
const debouncedProcess = debounce(processInput, 200);
// Rapid calls - only last one executes
debouncedProcess('first');
debouncedProcess('second');
const result = await debouncedProcess('third');
return result;
}
Throttling with Timers
export async function handler(event) {
function throttle(func, delay) {
let lastCall = 0;
return function(...args) {
const now = Date.now();
if (now - lastCall >= delay) {
lastCall = now;
return func(...args);
}
return null;
};
}
const results = [];
function logMessage(message) {
results.push({ message, timestamp: Date.now() });
}
const throttledLog = throttle(logMessage, 100);
// Rapid calls - some are ignored
for (let i = 0; i < 10; i++) {
throttledLog(`Message ${i}`);
await new Promise(resolve => setTimeout(resolve, 30));
}
return {
callsMade: 10,
callsExecuted: results.length,
results
};
}
Timeout with Promise Race
export async function handler(event) {
async function fetchWithTimeout(url, timeoutMs) {
const fetchPromise = simulateFetch(url);
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => {
reject(new Error('Request timeout'));
}, timeoutMs);
});
return Promise.race([fetchPromise, timeoutPromise]);
}
async function simulateFetch(url) {
await new Promise(resolve => setTimeout(resolve, 2000)); // 2s delay
return { data: 'Response from ' + url };
}
try {
const result = await fetchWithTimeout('https://api.example.com', 1000);
return result;
} catch (error) {
return { error: error.message };
}
}
Retry with Exponential Backoff
export async function handler(event) {
async function retryWithBackoff(fn, maxRetries = 3) {
let lastError;
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
lastError = error;
if (i < maxRetries - 1) {
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
console.log(`Retry ${i + 1} after ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
throw lastError;
}
let attempts = 0;
async function unreliableOperation() {
attempts++;
if (attempts < 3) {
throw new Error(`Attempt ${attempts} failed`);
}
return { success: true, attempts };
}
try {
const result = await retryWithBackoff(unreliableOperation);
return result;
} catch (error) {
return {
success: false,
error: error.message,
attempts
};
}
}
Execution Order
Understanding the execution order of timers:
- Synchronous code executes first
- process.nextTick() callbacks execute
- Promise microtasks execute
- setImmediate() callbacks execute
- setTimeout()/setInterval() callbacks execute (macrotasks)
Best Practices
- Use promise-based timers (
timers/promises) for cleaner async code - Always clear intervals when done to prevent memory leaks
- Use
setImmediate()for deferring work, notsetTimeout(fn, 0) - Consider using
AbortControllerwith promise-based timers for cancellation - Be careful with intervals - ensure they clear properly
- For delays, prefer
timers/promises.setTimeout()over callback-based version