The Node.js Event Loop

Understand event-loop phases, microtasks, nextTick, timers, and non-blocking I/O.

Lesson content

๐ŸŽฏ Goal By the end of this lesson, you'll understand: What is the Event Loop? Why do we need it? How it works Event Loop phases (basic) Real-world examples Interview questions What is the Event Loop? The Event Loop is the mechanism that allows Node.js to perform non-blocking asynchronous operations , even though JavaScript runs on a single thread . Simple Definition: The Event Loop continuously checks whether asynchronous tasks are complete. If they are, it executes their callbacks. Why Do We Need the Event Loop? JavaScript executes one statement at a time . If JavaScript waited for every file, database, or API request to finish, the entire application would stop responding. The Event Loop solves this problem. Real-Life Example ๐Ÿฝ๏ธ Imagine a waiter in a restaurant. Customer 1 โ†’ Orders Food Customer 2 โ†’ Orders Coffee Customer 3 โ†’ Pays Bill The waiter doesn't stand in the kitchen waiting for one order. Instead, the waiter: Takes an order Gives it to the kitchen Serves another customer Returns when the food is ready The waiter is like the Event Loop . How the Event Loop Works JavaScript Code โ”‚ โ–ผ Call Stack โ”‚ โ–ผ Async Task? โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ No Yes โ”‚ โ”‚ โ–ผ โ–ผ Execute Node.js Runtime (libuv) โ”‚ โ”‚ โ–ผ โ–ผ Continue Task Complete โ”‚ โ–ผ Callback Queue โ”‚ โ–ผ Event Loop โ”‚ โ–ผ Call Stack Example console . log( "Start" ); setTimeout (() => { console . log( "Timer" ); }, 2000 ); console . log( "End" ); Output Start End Timer Step-by-Step Execution Step 1 console . log( "Start" ); Output Start Step 2 setTimeout (...); Node.js sends the timer to libuv . Step 3 console . log( "End" ); Output End Step 4 After 2 seconds: Timer The Event Loop moves the callback to the Call Stack and executes it. Visualization Call Stack console.log("Start") โ†“ setTimeout() โ†“ console.log("End") โ†“ Empty Meanwhile libuv Wait 2 Seconds โ†“ Callback Queue โ†“ Event Loop โ†“ Call Stack โ†“ console.log("Timer") Event Loop Phases (Simplified) Node.js processes tasks in phases. Timers โ”‚ โ–ผ Pending Callbacks โ”‚ โ–ผ Idle / Prepare โ”‚ โ–ผ Poll โ”‚ โ–ผ Check โ”‚ โ–ผ Close Callbacks 1. Timers Phase Runs callbacks for: setTimeout () setInterval () 2. Poll Phase Handles: File Reading Database Operations Network Requests 3. Check Phase Runs: setImmediate () 4. Close Callbacks Runs cleanup events like: socket . close() Example with File Reading const fs = require ( "fs" ); console . log( "Start" ); fs . readFile( "test.txt" , () => { console . log( "File Read" ); }); console . log( "End" ); Output Start End File Read The Event Loop executes the file callback after the synchronous code completes. Example with setImmediate() setImmediate (() => { console . log( "Immediate" ); }); console . log( "Hello" ); Output Hello Immediate Event Loop vs Call Stack Call Stack Event Loop Executes JavaScript functions Watches for completed async tasks LIFO (Last In, First Out) Moves callbacks to the Call Stack Runs synchronous code Handles asynchronous callbacks Real-Life Example ๐Ÿ“ฆ Suppose you're waiting for three deliveries. Package A Package B Package C You continue working. Whenever a package arrives, you receive it immediately. That's how the Event Loop handles completed asynchronous tasks. Why is the Event Loop Important? Without the Event Loop: โŒ File reading would block the application. โŒ API calls would freeze the server. โŒ Multiple users couldn't be handled efficiently. With the Event Loop: โœ… Non-blocking I/O โœ… High performance โœ… Thousands of simultaneous connections Common APIs That Use the Event Loop setTimeout() setInterval() setImmediate() fs.readFile() Database Queries HTTP Requests Network Operations Interview Question What is the output? console . log( "1" ); setTimeout (() => { console . log( "2" ); }, 0 ); console . log( "3" ); Output 1 3 2 Reason Even with a 0 ms delay, the callback waits until the current synchronous code finishes and the Event Loop gets a chance to process it. Best Practices โœ… Use asynchronous APIs instead of blocking synchronous ones. โœ… Keep synchronous code short to avoid blocking the Event Loop. โœ… Use async/await for readable asynchronous code. โŒ Avoid CPU-intensive work on the main thread because it blocks the Event Loop. Key Points โœ… The Event Loop enables non-blocking I/O in Node.js. โœ… JavaScript runs on a single thread. โœ… libuv handles asynchronous operations in the background. โœ… The Event Loop moves completed callbacks to the Call Stack. โœ… Timers, file I/O, and network requests all rely on the Event Loop. ๐Ÿง  Easy Formula JavaScript Code โ”‚ โ–ผ Call Stack โ”‚ โ–ผ Async Task? โ”‚ Yes โ”€โ”€โ”€โ”€โ”€โ–บ libuv โ”‚ โ–ผ Callback Queue โ”‚ โ–ผ Event Loop โ”‚ โ–ผ Call Stack Remember: ๐Ÿงต JavaScript executes one task at a time. โšก The Event Loop keeps checking for completed asynchronous tasks. ๐Ÿš€ The Event Loop is the heart of Node.js's non-blocking architecture.