bugl
bugl
HomeLearnPatternsPathsSearch
HomeLearnPatternsPathsSearch

Loading lesson path

Learn/Node.js/Core Modules
Node.js•Core Modules

Node.js Timers Module

Flash cards

Review the key moves

1/4
Core idea

What is the main idea behind Node.js Timers Module?

Lesson checks

Practice each idea before moving on

Short Mimo-style checks built from this lesson's code, terms, and sequence.

1Quick choice

Which statement best captures the main point of this lesson?

2Fill blank

Complete the missing token from the example code.

___ { setTimeout, setInterval, setImmediate } = require('timers');
3Order

Put the learning moves in the order that makes the concept easiest to apply.

Using the Timers Module
Basic Timer Example
Getting Started with Timers

What is the Timers Module?

The Timers module provides functions that help schedule code execution at specific times or intervals.

Unlike browser JavaScript, Node.js timing functions are provided as part of the Timers module, though they are available globally without requiring an explicit import.

Key features include

  • Delayed execution with setTimeout()
  • Repeated execution with setInterval()
  • Immediate execution in the next event loop with setImmediate()
  • Promise-based APIs for modern async/await patterns

These capabilities are essential for building responsive applications, implementing polling, handling delayed operations, and more.

Getting Started with Timers

Here's a quick example of using the Timers module to schedule code execution:

Basic Timer Example

const { setTimeout, setInterval, setImmediate } = require('timers');
console.log('Starting timers...');
// Execute once after delay
setTimeout(() => {
 console.log('This runs after 1 second');
}, 1000);
// Execute repeatedly at interval
let counter = 0;
const interval = setInterval(() => {
 counter++;
 console.log(`Interval tick ${counter}`);
 if (counter >= 3) clearInterval(interval);
}, 1000);
// Execute in the next event loop iteration
setImmediate(() => {
 console.log('This runs in the next iteration of the event loop');
});
console.log('Timers scheduled');

Using the Timers Module

The Timers module's functions are available globally, so you don't need to require them explicitly.

However, if you want to access advanced features or for clarity, you can import the module:

const timers = require('timers');
// Or, for the promises API (Node.js 15.0.0+)
const timersPromises = require('timers/promises');

setTimeout() and clearTimeout()

The setTimeout() function schedules execution of a callback after a specified amount of time (in milliseconds).

It returns a Timeout object that can be used to cancel the timeout.

Common Use Cases

  • Delaying execution of non-critical tasks
  • Implementing timeouts for operations
  • Breaking up CPU-intensive tasks
  • Implementing retry logic
// Basic usage
setTimeout(() => {
 console.log('This message is displayed after 2 seconds');
}, 2000);
// With arguments
setTimeout((name) => {
 console.log(`Hello, ${name}!`);
}, 1000, 'World');
// Storing and clearing a timeout
const timeoutId = setTimeout(() => {
 console.log('This will never be displayed');
}, 5000);
// Cancel the timeout before it executes
clearTimeout(timeoutId);
console.log('Timeout has been cancelled');

Promise-Based setTimeout

Node.js 15.0.0 and later provide a promises-based API for timers:

const { setTimeout } = require('timers/promises');
async function delayedGreeting() {
 console.log('Starting...');
 // Wait for 2 seconds
 await setTimeout(2000);
 console.log('After 2 seconds');
 // Wait for 1 second with a value
 const result = await setTimeout(1000, 'Hello, World!');
 console.log('After 1 more second:', result);
}
delayedGreeting().catch(console.error);

setInterval() and clearInterval()

The setInterval() function calls a function repeatedly at specified intervals (in milliseconds).

It returns an Interval object that can be used to stop the interval.

Common Use Cases

  • Polling for updates
  • Running periodic maintenance tasks
  • Implementing heartbeat mechanisms
  • Updating UI elements at regular intervals

Note

The actual interval between executions may be longer than specified if the event loop is blocked by other operations.

// Basic interval
let counter = 0;
const intervalId = setInterval(() => {
 counter++;
 console.log(`Interval executed ${counter} times`);
 // Stop after 5 executions
 if (counter >= 5) {
 clearInterval(intervalId);
 console.log('Interval stopped');
 }
}, 1000);
// Interval with arguments
const nameInterval = setInterval((name) => {
 console.log(`Hello, ${name}!`);
}, 2000, 'Node.js');
// Stop the name interval after 6 seconds
setTimeout(() => {
 clearInterval(nameInterval);
 console.log('Name interval stopped');
}, 6000);

Promise-Based setInterval

Using the promises API for intervals

const { setInterval } = require('timers/promises');
async function repeatedGreeting() {
 console.log('Starting interval...');
 // Create an async iterator from setInterval
 const interval = setInterval(1000, 'tick');
 // Limit to 5 iterations
 let counter = 0;
 for await (const tick of interval) {
 console.log(counter + 1, tick);
 counter++;
 if (counter >= 5) {
 break; // Exit the loop, stopping the interval
 }
 }
 console.log('Interval finished');
}
repeatedGreeting().catch(console.error);

setImmediate() and clearImmediate()

The setImmediate() function schedules a callback to run in the next iteration of the event loop, after I/O events but before timers.

It's similar to using setTimeout(callback, 0) but more efficient.

When to Use setImmediate()

  • When you want to execute code after the current operation completes
  • To break up long-running operations into smaller chunks
  • To ensure callbacks run after I/O operations complete
  • In recursive functions to prevent stack overflows
console.log('Start');
setTimeout(() => {
 console.log('setTimeout callback');
}, 0);
setImmediate(() => {
 console.log('setImmediate callback');
});
process.nextTick(() => {
 console.log('nextTick callback');
});
console.log('End');

The execution order will typically be

  • Start
  • End
  • nextTick callback
  • setTimeout callback or setImmediate callback (order can vary)

Note

The order of execution between setTimeout(0) and setImmediate() can be unpredictable when called from the main module.

However, inside an I/O callback, setImmediate() will always execute before any timers.

Canceling an Immediate

const immediateId = setImmediate(() => {
 console.log('This will not be displayed');
});
clearImmediate(immediateId);
console.log('Immediate has been cancelled');

process.nextTick()

Although not part of the Timers module, process.nextTick() is a related function that defers a callback until the next iteration of the event loop, but executes it before any I/O events or timers.

Key Characteristics

  • Runs before any I/O events or timers
  • Higher priority than setImmediate()
  • Processes all queued callbacks before the event loop continues
  • Can lead to I/O starvation if overused

When to Use process.nextTick()

  • To ensure a callback runs after the current operation but before any I/O
  • To break up long-running operations
  • To allow event handlers to be set up after an object is created
  • To ensure consistent API behavior (e.g., making constructors work with or without new)
console.log('Start');
// Schedule three different types of callbacks
setTimeout(() => {
 console.log('setTimeout executed');
}, 0);
setImmediate(() => {
 console.log('setImmediate executed');
});
process.nextTick(() => {
 console.log('nextTick executed');
});
console.log('End');

Note

process.nextTick() fires immediately on the same phase of the event loop, while setImmediate() fires on the following iteration or 'tick' of the event loop.

Debouncing

Prevent a function from being called too frequently by delaying its execution:

function debounce(func, delay) {
 let timeoutId;
 return function(...args) {
 clearTimeout(timeoutId);
 timeoutId = setTimeout(() => func.apply(this, args), delay);
 };
}
// Example usage
const handleResize = debounce(() => {
 console.log('Window resized');
}, 300);
// Call handleResize() on window resize

Throttling

Limit how often a function can be called over time:

function throttle(func, limit) {
 let inThrottle = false;
 return function(...args) {
 if (!inThrottle) {
 func.apply(this, args);
 inThrottle = true;
 setTimeout(() => inThrottle = false, limit);
 }
 };
}
// Example usage
const handleScroll = throttle(() => {
 console.log('Handling scroll');
}, 200);
// Call handleScroll() on window scroll

Sequential Timeouts

Execute a series of operations with delays between them:

function sequentialTimeouts(callbacks, delay = 1000) {
 let index = 0;
 function next() {
 if (index < callbacks.length) {
 callbacks[index]();
 index++;
 setTimeout(next, delay);
 }
 }
 next();
}
// Example usage
sequentialTimeouts([
 () => console.log('Step 1'),
 () => console.log('Step 2'),
 () => console.log('Step 3')
], 1000);

Timer Precision and Performance

Node.js timers are not precise to the millisecond. The actual delay might be slightly longer due to:

  • System load and CPU usage
  • Event loop blocking operations
  • Other timers and I/O operations
  • System timer resolution (typically 1-15ms)
const desiredDelay = 100; // 100ms
const start = Date.now();
setTimeout(() => {
 const actualDelay = Date.now() - start;
 console.log(`Desired delay: ${desiredDelay}ms`);
 console.log(`Actual delay: ${actualDelay}ms`);
 console.log(`Difference: ${actualDelay - desiredDelay}ms`);
}, desiredDelay);

Memory and Resource Management

Proper management of timers is crucial to prevent memory leaks and excessive resource usage:

// Leak: Interval keeps running even if not needed
function startService() {
 setInterval(() => {
 fetchData();
 }, 1000);
}
// Leak: Timeout with closure over large object
function processData(data) {
 setTimeout(() => {
 console.log('Processing complete');
 // 'data' is kept in memory until the timeout fires
 }, 10000, data);
}
  • Always clear intervals and timeouts when they're no longer needed
  • Store timer IDs in a way that allows for cleanup
  • Be cautious with closures in timer callbacks
  • Use clearTimeout() and clearInterval() in cleanup functions

Remember to clear timers when they're no longer needed, especially in long-running applications, to prevent memory leaks:

// Bad practice in a server context
function startServer() {
 setInterval(() => {
 // This interval will run forever and prevent proper cleanup
 console.log('Server is running...');
 }, 60000);
}
// Better practice
function startServer() {
 const intervalId = setInterval(() => {
 console.log('Server is running...');
 }, 60000);
 // Store the interval ID for later cleanup
 return {
 stop: () => {
 clearInterval(intervalId);
 console.log('Server stopped');
 }
 };
}
// Example usage
const server = startServer();
// Stop the server after 3 minutes
setTimeout(() => {
 server.stop();
}, 180000);

Zero-Delay Timeouts

When using setTimeout(callback, 0) , the callback doesn't execute immediately.

It executes after the current event loop cycle completes, which can be used to "break up" CPU-intensive tasks:

function processArray(array, processFunction) {
 const chunkSize = 1000;
 let index = 0;
 function processChunk() {
 const chunk = array.slice(index, index + chunkSize);
 chunk.forEach(processFunction);
 index += chunkSize;
 if (index < array.length) {
 setTimeout(processChunk, 0); // Yield to the event loop
 } else {
 console.log('Processing complete');
 }
}
processChunk();
}
// Example usage
const bigArray = Array(10000).fill().map((_, i) => i);
console.log('Starting processing...');
processArray(bigArray, (item) => {
 // Simple processing
 if (item % 5000 === 0) {
 console.log(`Processed item ${item}`);
 }
});
console.log('This will log before processing completes');

Previous

Node.js Crypto Module

Next

Node.js DNS Module