Facebook Pixel

How Async I/O Works in Node.js Through libuv

Async I/O is the core of Node.js. Here is how it works through libuv, step by step.

How Async I/O Works in Node.js Through libuv

Async I/O is the core of Node.js's performance. Here is how it works through libuv.

The Async I/O Model

When JavaScript calls an async I/O operation like reading a file, the operation is handed to libuv. The JavaScript thread does not wait; it continues with other work. When the operation completes, libuv queues the callback, and the event loop runs it.

Step 1: JavaScript Calls an Async API

When you call fs.readFile, the JavaScript implementation in the lib directory calls a C++ binding. The binding delegates the actual file read to libuv.

Step 2: libuv Handles the Operation

libuv uses the operating system's async I/O capabilities (epoll on Linux, kqueue on macOS, IOCP on Windows) or the thread pool for operations that cannot be done async. The operation runs off the main thread.

Step 3: The Callback Is Queued

When the operation completes, libuv queues the callback in the event loop. The event loop processes callbacks in phases: timers, pending callbacks, poll, check, and close.

Step 4: The Event Loop Runs the Callback

The event loop, on its next poll phase, picks up the callback and runs it on the main thread. This is when your JavaScript callback executes with the result of the I/O operation.

Why This Is Efficient

The main thread is never blocked waiting for I/O. While one request waits for a database query, the event loop processes other requests' callbacks. This lets Node.js handle thousands of concurrent connections on one thread.

The Takeaway

Async I/O in Node.js works by delegating operations to libuv, which handles them off the main thread and queues callbacks when complete. The event loop processes these callbacks on the main thread, keeping it free for other work. This is why Node.js scales for I/O-bound work.

When JavaScript calls an async I/O operation, it is delegated to libuv, which handles it off the main thread using the OS's async capabilities or the thread pool. When complete, libuv queues the callback, and the event loop runs it on the main thread.

libuv handles the actual I/O operation off the main thread, using the OS's async capabilities (epoll, kqueue, IOCP) or the thread pool. When the operation completes, libuv queues the callback for the event loop to process.

The event loop processes callbacks in phases: timers, pending callbacks, poll, check, and close. When libuv queues a completed I/O callback, the event loop picks it up on its next poll phase and runs it on the main thread.

Because the main thread is never blocked waiting for I/O. While one request waits for a database query, the event loop processes other requests' callbacks. This lets Node.js handle thousands of concurrent connections on one thread.

libuv uses its thread pool (default 4 threads) to run the operation off the main thread. This prevents blocking the event loop for operations that the OS cannot handle asynchronously, like some file system operations on certain platforms.

Ready to master Node.js completely?

Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.

Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.