[Roadmap_Node] 5_Core Modules

Table of Contents

Introduction

Node.js core modules are pre-built blocks of functionality that come bundled with the Node.js installation. They provide essential tools for common development tasks, saving you time and effort from writing everything from scratch.

Benefits of Using Core Modules:

Some Common Core Modules:

File System (fs)

fs (File System): Interact with the file system on your server. You can use it for:

Here’s an example that demonstrates basic file system operations using Node.js core modules:

1. Reading a File:

const fs = require("fs");

const filePath = "my-file.txt";

// Read the file asynchronously
fs.readFile(filePath, "utf-8", (err, data) => {
  if (err) {
    console.error("Error reading file:", err);
  } else {
    console.log("File content:", data);
  }
});

console.log("This line is executed before the file is read"); // Non-blocking

Explanation:

2. Writing a File:

const fs = require("fs");

const filePath = "new-file.txt";
const fileContent = "This is some new content for the file.";

// Write the file asynchronously
fs.writeFile(filePath, fileContent, "utf-8", (err) => {
  if (err) {
    console.error("Error writing file:", err);
  } else {
    console.log("File written successfully");
  }
});

console.log("This line is executed before the file is written"); // Non-blocking

Explanation:

3. Checking File Existence:

const fs = require("fs");

const filePath = "my-file.txt";

// Check if the file exists asynchronously
fs.access(filePath, fs.constants.F_OK, (err) => {
  if (err) {
    console.error("File does not exist");
  } else {
    console.log("File exists");
  }
});

console.log("This line is executed before the file check"); // Non-blocking

Explanation:

These are just basic examples. The fs module offers many more functionalities for file system operations in Node.js, including creating directories, renaming files, and deleting files. Remember to handle errors appropriately in your real-world applications.

HyperText Transfer Protocol (http)

http (HyperText Transfer Protocol): Build web servers and clients:

Here’s an example that demonstrates a basic HTTP server and client interaction in Node.js:

1. HTTP Server (server.js):

const http = require("http");

const hostname = "localhost";
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader("Content-Type", "text/plain");
  res.end("Hello, World!\n");
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Explanation:

2. HTTP Client (client.js):

const http = require("http");

const hostname = "localhost";
const port = 3000;

const request = http.get(`http://${hostname}:${port}/`, (response) => {
  console.log(`statusCode: ${response.statusCode}`);
  console.log("headers:", response.headers);

  response.on("data", (chunk) => {
    console.log(chunk.toString());
  });
});

request.on("error", (error) => {
  console.error(error);
});

Explanation:

Running the Example:

  1. Save the server code as server.js and the client code as client.js.
  2. Run the server: node server.js (This keeps the server running in the background).
  3. Run the client: node client.js.

The client should output the response status code (200), headers, and the response content (“Hello, World!”).

Note: This is a very basic example. Real-world HTTP servers and clients often involve more complex interactions, including handling different HTTP methods (GET, POST, etc.), parsing request bodies, and sending more comprehensive responses.

Path Manipulation (path)

path (Path Manipulation): Work with file and directory paths in a platform-independent way:

Here’s an example demonstrating how to use the path module for manipulating file and directory paths in Node.js:

const path = require("path");

// Example path
const filePath = "Users/john/documents/report.txt";

// Get the filename
const filename = path.basename(filePath);
console.log("Filename:", filename); // Output: report.txt

// Get the directory name
const dirname = path.dirname(filePath);
console.log("Directory:", dirname); // Output: Users/john/documents

// Get the file extension
const extname = path.extname(filePath);
console.log("Extension:", extname); // Output: .txt

// Join path segments
const newFilePath = path.join(__dirname, "data", "new-file.csv");
console.log("New file path:", newFilePath); // Output: (your current directory path)/data/new-file.csv

// Normalize a path (handles "..")
const normalizedPath = path.normalize("/users/./john/../public/main.js");
console.log("Normalized path:", normalizedPath); // Output: /users/public/main.js

// Check if a path is absolute
const isAbsolute = path.isAbsolute(filePath);
console.log("Is absolute path:", isAbsolute); // Output: false

Explanation:

  1. Require path Module: We require the path module to access its functionalities.

  2. Example Path: We define a sample file path (filePath) for demonstration.

  3. basename: This function extracts the filename from the provided path, excluding the directory path.

  4. dirname: This function extracts the directory name from the provided path, excluding the filename.

  5. extname: This function extracts the file extension (including the dot) from the provided path.

  6. path.join: This function joins multiple path segments into a single normalized path. It’s platform-independent and handles separators appropriately. In this case, we use __dirname (current directory path) to construct a new file path within the data directory.

  7. path.normalize: This function normalizes a given path by resolving occurrences of ”..” or ”.” in the path. This can be useful for handling relative paths that might contain these components.

  8. path.isAbsolute: This function checks if a given path is an absolute path (starts with a drive letter on Windows or a forward slash on Unix-like systems).

Remember:

By understanding these functions, you can effectively manipulate file and directory paths in your Node.js applications, ensuring platform-independent behavior and proper path handling.

Event Emitter

events (Event Emitter): Create applications that react to various events and user interactions:

Here’s an example of an event emitter in Node.js that demonstrates communication between different parts of your application:

1. Event Emitter Class (EventEmitter.js):

const { EventEmitter } = require("events");

class MyEventEmitter extends EventEmitter {
  constructor() {
    super();
  }

  emitError(errorMessage) {
    this.emit("error", errorMessage);
  }

  emitData(data) {
    this.emit("data", data);
  }
}

module.exports = MyEventEmitter;

Explanation:

2. Usage Example (main.js):

const MyEventEmitter = require("./EventEmitter");

const emitter = new MyEventEmitter();

// Listener function for the 'error' event
emitter.on("error", (errorMessage) => {
  console.error("Error:", errorMessage);
});

// Listener function for the 'data' event
emitter.on("data", (data) => {
  console.log("Data received:", data);
});

// Emit events from somewhere in your application
emitter.emitError("Something went wrong!");
emitter.emitData("This is some important data");

Explanation:

Benefits of Event Emitters:

In essence:

Event emitters provide a flexible way to create event-driven applications in Node.js. By emitting and listening to events, you can establish communication channels between different parts of your code, making it more organized and responsive.

URL

url (URL Parsing): Parse and manipulate URLs:

Here’s an example of URL parsing in Node.js using the built-in url module:

const url = require("url");

const fullUrl =
  "https://user:pass@sub.example.com:8080/p/a/t/h?query=string#hash";

// Parse the URL
const parsedUrl = url.parse(fullUrl, true); // Set 'true' for query object

console.log("Protocol:", parsedUrl.protocol); // Output: https:
console.log("Username:", parsedUrl.username); // Output: user
console.log("Password:", parsedUrl.password); // Output: pass
console.log("Hostname:", parsedUrl.hostname); // Output: sub.example.com
console.log("Port:", parsedUrl.port); // Output: 8080
console.log("Pathname:", parsedUrl.pathname); // Output: /p/a/t/h
console.log("Query:", parsedUrl.query); // Output: { query: 'string' } (object with key-value pairs)
console.log("Hash:", parsedUrl.hash); // Output: #hash

// Access specific query string parameters
console.log("Query parameter (query):", parsedUrl.query.query); // Output: string

Explanation:

  1. Require url Module: We require the url module to access URL parsing functionalities.

  2. Define a URL: We define a sample URL (fullUrl) that includes various components like protocol, username, password, hostname, port, pathname, query string, and hash.

  3. url.parse: This function parses the provided URL string and returns an object containing its components. The second argument (true) specifies that we want the query string to be parsed into an object with key-value pairs (instead of a single string).

  4. Accessing URL Components: We access individual URL components using properties on the parsedUrl object:

    • protocol: The protocol (e.g., “http:”, “https:”).
    • username: The username portion of the URL credentials (if present).
    • password: The password portion of the URL credentials (if present).
    • hostname: The hostname or domain name.
    • port: The port number (if specified, defaults to 80 for http and 443 for https).
    • pathname: The path portion of the URL (the path to a resource on the server).
    • query: An object containing key-value pairs representing the query string parameters (if present).
    • hash: The hash fragment part of the URL (starting with ”#”).
  5. Accessing Query String Parameters: If the URL includes a query string, the query property becomes an object where each key-value pair is represented as a property-value pair within the object. We can access specific parameters using their names.

Remember:

By understanding URL parsing, you can effectively extract information from URLs in your Node.js applications, allowing you to process data based on specific URL components or query string parameters.

Conclusion

This was a more difficult post to digest but hopefully it can help you understand the different parts that makes Node JS core modules. Seeing them in action should give you a better understanding them and don’t be afraid to re-read this post as much as you need even before interviews to help you out.

See you on the next post.

Sincerely,

Eng. Adrian Beria