<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dương</title>
    <description>The latest articles on DEV Community by Dương (@duong19639775).</description>
    <link>https://dev.to/duong19639775</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1303928%2F838cdf69-38c0-4eed-b584-c0738db8fe6a.jpg</url>
      <title>DEV Community: Dương</title>
      <link>https://dev.to/duong19639775</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/duong19639775"/>
    <language>en</language>
    <item>
      <title>Exploring Libuv: Asynchronous I/O in Node.js on Linux, macOS, and Windows</title>
      <dc:creator>Dương</dc:creator>
      <pubDate>Sat, 19 Oct 2024 16:29:12 +0000</pubDate>
      <link>https://dev.to/duong19639775/exploring-libuv-asynchronous-io-in-nodejs-on-linux-macos-and-windows-gdp</link>
      <guid>https://dev.to/duong19639775/exploring-libuv-asynchronous-io-in-nodejs-on-linux-macos-and-windows-gdp</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
Node.js is a powerful platform for developing network applications, renowned for its ability to handle asynchronous I/O tasks. Libuv is the core library that provides the event loop and APIs for Node.js to manage I/O. This article will delve into how libuv operates, providing specific examples of I/O handling in Node.js across different operating systems while explaining how libuv interacts with the operating system and how the event loop processes callbacks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Libuv?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Libuv is an open-source library designed to provide asynchronous I/O capabilities in Node.js. It supports features such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Event Loop: Manages I/O tasks and ensures they do not block the main 
thread.&lt;/li&gt;
&lt;li&gt;Cross-Platform Support: Provides a unified API for different 
operating systems such as Linux, macOS, and Windows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How Libuv Handles I/O in Node.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The process of handling I/O in Node.js occurs as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Receiving Requests: When a request from a client arrives at the 
 server, libuv adds the request to the event loop.&lt;/li&gt;
&lt;li&gt;Performing I/O: Libuv calls asynchronous I/O functions without 
 blocking the main loop. It sends requests to the operating system to 
 perform operations like reading files or accessing databases.&lt;/li&gt;
&lt;li&gt;Callback: When the I/O operation is complete, the callback is 
 invoked to process the result and send a response back to the 
 client.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Callback Processing in the Event Loop&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When the operating system signals that an I/O task is complete, libuv performs the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding Callback to Task Queue: Libuv adds the corresponding callback 
 to the task queue for processing after the event loop completes its 
 current tasks.&lt;/li&gt;
&lt;li&gt;Processing Callback: The event loop checks the task queue. If there 
 are any callbacks in the queue, they are retrieved and executed.&lt;/li&gt;
&lt;li&gt;Continuing Processing: After the callback completes, the event loop 
 returns to check the queue and repeats the process until there are 
 no more callbacks to handle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffzpjgz4ckhquituzjrvy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffzpjgz4ckhquituzjrvy.png" alt="Image description" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Specific Examples of I/O Handling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. On Linux&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Reading a JSON File&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const fs = require('fs');
const app = express();
const port = 3000;

// Route to read JSON file
app.get('/data', (req, res) =&amp;gt; {
    fs.readFile('data.json', 'utf8', (err, data) =&amp;gt; {
        if (err) {
            console.error('Error reading file:', err);
            return res.status(500).send('Internal Server Error');
        }
        res.send(data);
    });
});

// Start server
app.listen(port, () =&amp;gt; {
    console.log(`Server running on http://localhost:${port}`);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When a client sends a GET request to /data, libuv uses epoll, a 
 high-performance I/O mechanism in Linux, to monitor the socket.&lt;/li&gt;
&lt;li&gt;The fs.readFile function is called to read the contents of 
 data.json. Libuv sends this request to the Linux kernel, using epoll 
 to monitor the I/O status without blocking the event loop.&lt;/li&gt;
&lt;li&gt;When the reading operation completes, the kernel sends a signal back 
 to libuv, and the callback is added to the task queue.&lt;/li&gt;
&lt;li&gt;When the event loop continues, it checks the queue and executes the 
 callback, returning the data to the client.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. On macOS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Logging Request Time&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const fs = require('fs');
const app = express();
const port = 3000;

// Route to log request time
app.get('/log', (req, res) =&amp;gt; {
    const logMessage = `Request received at: ${new Date().toISOString()}\n`;

    fs.appendFile('requests.log', logMessage, (err) =&amp;gt; {
        if (err) {
            console.error('Error logging request:', err);
            return res.status(500).send('Internal Server Error');
        }
        res.send('Request logged successfully!');
    });
});

// Start server
app.listen(port, () =&amp;gt; {
    console.log(`Server running on http://localhost:${port}`);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When a client sends a request to /log, libuv uses kqueue to monitor 
 events from the socket.&lt;/li&gt;
&lt;li&gt;The fs.appendFile function is called to write the time the request 
 was received into requests.log. Libuv sends this request to the 
 macOS kernel through kqueue, allowing it to monitor the I/O event 
 without blocking the main loop.&lt;/li&gt;
&lt;li&gt;When the logging operation completes, the kernel notifies libuv, and 
 the callback is added to the task queue.&lt;/li&gt;
&lt;li&gt;The event loop continues to check the queue and executes the 
 callback to notify the client of the result.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. On Windows&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Returning JSON Data&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const app = express();
const port = 3000;

// Route to return JSON data
app.get('/json', (req, res) =&amp;gt; {
    const responseData = {
        message: 'Hello from Node.js!',
        timestamp: new Date().toISOString(),
    };

    res.json(responseData);
});

// Start server
app.listen(port, () =&amp;gt; {
    console.log(`Server running on http://localhost:${port}`);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the GET request to /json is sent to the server, libuv uses I/O 
 Completion Ports (IOCP) to manage the socket connections.&lt;/li&gt;
&lt;li&gt;The server returns a JSON object. Libuv performs this operation 
 through IOCP, allowing the Windows kernel to notify libuv when the 
 data is ready to send.&lt;/li&gt;
&lt;li&gt;When the operation is complete, libuv adds the callback to the task 
 queue for later processing.&lt;/li&gt;
&lt;li&gt;The event loop continues its work, checking the queue and executing 
 the callback to send the response back to the client.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
  </channel>
</rss>
