Node.js is awesome for non-blocking tasks, but heavy work can still jam the event loop, slowing things down. That’s where setImmediate
helps—it moves tasks to the next step, keeping your app running smoothly. In this short guide, we’ll tackle a real problem, check a use case, and see how setImmediate
increases throughput. Let’s begin!
Problem: Analysing Large Text Data (Customer Reviews)
Imagine your app gets 1,00,000 customer reviews from an API and needs to analyse their sentiment (positive or negative). Doing it all at once blocks the event loop.
Problem Code:
const reviews = Array(100000).fill().map((_, i) => ({
id: i,
text: `This is review number ${i}. Product is good but service can improve.`
}));
function analyzeSentiment(reviews) {
return reviews.map(review => {
const words = review.text.split(' '); // Tokenize
let score = 0;
// Simple scoring: count positive/negative words
words.forEach(word => {
if (['good', 'awesome'].includes(word)) score += 1;
if (['bad', 'improve'].includes(word)) score -= 1;
});
return { id: review.id, score };
});
}
console.log('Starting...');
const results = analyzeSentiment(reviews); // Blocks for ~100-200ms
console.log('Analyzed reviews:', results.length);
console.log('Done!');
What’s the Issue? Analysing 1,00,000 reviews—splitting text and scoring—takes enough CPU time to freeze the event loop. On a server, this delays API responses or other tasks, hurting performance.
Solution: Use setImmediate
to split it:
function analyzeSentimentChunk(reviews, callback) {
const CHUNK_SIZE = 10_000;
let index = 0;
const result = [];
function processChunk() {
const end = Math.min(index + CHUNK_SIZE, reviews.length);
for (; index < end; index++) {
const words = reviews[index].text.split(' ');
let score = 0;
words.forEach(word => {
if (['good', 'awesome'].includes(word)) score += 1;
if (['bad', 'improve'].includes(word)) score -= 1;
});
result.push({ id: reviews[index].id, score });
}
if (index < reviews.length) {
setImmediate(processChunk);
} else {
callback(result);
}
}
setImmediate(processChunk);
}
const reviews = Array(100000).fill().map((_, i) => ({
id: i,
text: `This is review number ${i}. Product is good but service can improve.`
}));
console.log('Starting...');
analyzeSentimentChunk(reviews, (results) => {
console.log('Analyzed reviews:', results.length);
});
console.log('This runs instantly!');
Why It Works: We process 10_000 reviews per cycle, and setImmediate
schedules the next batch. The event loop stays free for other tasks.
Benefits:
- Non-blocking: App keeps handling requests or I/O.
- Better Throughput: More tasks run at once.
Drawbacks:
- Takes a bit longer due to scheduling.
- Chunk size needs tuning for best results.
Real Use: Ideal for text analysis (sentiment, keywords), log processing, or batch data transformations in APIs.
How Throughput Improves
Throughput is how many tasks your app can finish per second. Without setImmediate
, a 100-200ms blocking task stops everything for that time. Split into 10-20ms chunks, Node.js can handle other work in between—like serving API requests. This keeps your app responsive and lets it process more tasks under load, though exact gains depend on your setup and traffic.
Conclusion
setImmediate
boosts throughput in Node.js by splitting big tasks (like analysing customer reviews). It adds a small delay but keeps the app responsive.
Why not process.nextTick
?
--It runs too fast, delaying I/O by overloading the current tick.
Why not setTimeout(() => {}, 0)
?
It’s slower with extra timer delay.
For heavy CPU tasks (like image processing), worker threads are better—they run separately and other use case consider stream API. But for a simple fix, setImmediate
rocks—try it to keep your app smooth and responsive!
Top comments (0)