0% found this document useful (0 votes)
13 views45 pages

Understanding Node.js: Overview & Uses

Node.js is an open-source JavaScript runtime environment that allows developers to execute JavaScript code outside the browser, primarily on the server side, using Google's V8 engine. It is designed for building real-time applications and utilizes an event-driven, non-blocking I/O model for efficiency. Node.js is widely used for creating APIs, web servers, and real-time applications, and is supported by a rich ecosystem of packages managed through the Node Package Manager (NPM).
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views45 pages

Understanding Node.js: Overview & Uses

Node.js is an open-source JavaScript runtime environment that allows developers to execute JavaScript code outside the browser, primarily on the server side, using Google's V8 engine. It is designed for building real-time applications and utilizes an event-driven, non-blocking I/O model for efficiency. Node.js is widely used for creating APIs, web servers, and real-time applications, and is supported by a rich ecosystem of packages managed through the Node Package Manager (NPM).
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

NodeJS

What is [Link]?
Definition
[Link] is an open-source, cross-platform, JavaScript runtime environment that allows developers to
run JavaScript code outside the browser — typically on the server side.
It uses Google Chrome’s V8 JavaScript engine, the same engine that powers the Chrome browser, to
execute code.

Key Points
• Built on V8 Engine (fast execution of JS code).
• Uses Event-driven, non-blocking I/O model — making it lightweight and efficient.
• Ideal for building real-time, data-intensive applications.
• Runs on various OS like Windows, Linux, macOS.

Think of [Link] as a “JavaScript runtime factory” — instead of only running JS inside browsers (like
Chrome or Firefox), Node lets you run JS directly on your computer/server to build web apps or backend
services.

Example
File: [Link]
// Print a message
[Link]("Hello, [Link]!");
Run in terminal:
node [Link]
Output:
Hello, [Link]!
Explanation:
Node executes the JS file using its V8 engine — no browser needed.
This is the simplest form of Node program.

History & Evolution of [Link]


Year Event
2009 [Link] created by Ryan Dahl.
2010 NPM (Node Package Manager) introduced.
2011 Adoption by large companies like LinkedIn and Microsoft.
2012–2014 Node gained popularity for real-time apps and scalability.
2015 [Link] Foundation formed to support open-source growth.
2019–Present Used worldwide for backend APIs, serverless, IoT, and microservices.

Why Ryan Dahl created [Link]


Ryan wanted to:
• Handle high concurrency like chat or file uploads.
• Avoid blocking I/O problems found in traditional web servers (like Apache).
• Use a single programming language (JavaScript) across client and server.

Example (Problem [Link] Solved)


Earlier in PHP or Java, each user connection created a new thread, using heavy memory.
[Link] introduced:
• Single-threaded event loop
• Non-blocking I/O
This allowed handling thousands of requests concurrently with fewer resources.

Where [Link] is Used (Real-World Applications)


1. APIs and Web Servers
[Link] is widely used to create RESTful APIs and backend servers.
Example:
Netflix, PayPal, Uber use [Link] to handle millions of API requests per second.
Code Example:
const http = require('http');
const server = [Link]((req, res) => {
[Link](200, {'Content-Type': 'text/plain'});
[Link]('Hello from [Link] Server!');
});
[Link](3000, () => {
[Link]('Server running on [Link]
});
Output in Browser:
Hello from [Link] Server!
Explanation:
• [Link]() creates a web server.
• It listens on port 3000.
• Handles client requests asynchronously (non-blocking).

2. Real-Time Applications
• Chat applications (like Slack) or live gaming platforms.
• Built using WebSockets for two-way communication.
Example Framework: [Link]

3. Streaming Applications
Node supports streaming of data — useful for video/audio streaming platforms (like Netflix).

4. Internet of Things (IoT)


[Link] efficiently handles thousands of sensor connections due to its event-driven architecture.

5. Microservices & Serverless Apps


• [Link] works great for modular, distributed apps.
• Used in AWS Lambda, Google Cloud Functions.

[Link] Architecture
• [Link] uses a single-threaded event-driven architecture, built on top of Google’s V8 JavaScript
engine and libuv library (for asynchronous I/O operations).
• It efficiently handles multiple concurrent operations without creating multiple threads per request.
1. Application Layer
This is your JavaScript code — the part you write as a developer.
Examples:
const fs = require('fs');
[Link]('[Link]', (err, data) => {
if (err) throw err;
[Link]([Link]());
});
• You write asynchronous JavaScript code.
• When I/O operations (like reading a file, network calls, DB access) are needed, [Link] delegates
these to the libuv system.
• The code runs inside the V8 engine.

2. V8 Engine
• Developed by Google (used in Chrome).
• It converts JavaScript code into machine code for fast execution.
• It handles the execution of your JS logic — variables, loops, functions, etc.
Think of it as the brain that executes all your JavaScript.

3. [Link] Bindings
• These are C/C++ bindings that connect the V8 engine to libuv and the operating system.
• They act like a bridge between your JS code and low-level OS features (like file systems, sockets,
threads, etc.).
Example: When you use [Link](), the call goes through [Link] bindings before reaching the OS.
They are part of Node’s “glue code” that enables JavaScript to talk to native libraries.

4. Libuv (Asynchronous I/O Library)


This is the core part that makes [Link] non-blocking and event-driven.
Libuv provides:
• Event Loop
• Thread Pool
• Asynchronous I/O operations (file, network, process)

Event Loop
The event loop constantly runs in the background and checks:
• Are there any events to handle (like I/O completion)?
• Are there callbacks waiting to be executed?
It follows this cycle:
1. Wait for tasks/events.
2. Pick a callback from the Event Queue.
3. Execute the callback using the V8 engine.
4. Repeat.
This makes [Link] single-threaded but asynchronous.

Event Queue
• A queue (FIFO) that stores all callbacks or events waiting to be executed.
• Once the event loop finds that the V8 thread is free, it picks a callback from the queue and executes
it.

Thread Pool
Even though [Link] is single-threaded, libuv maintains a thread pool (default: 4 threads).
When you do tasks like:
• File system I/O
• DNS lookup
• Network requests
• Compression
libuv delegates these to the thread pool so they run in parallel (background threads).
Once done, results are sent back to the Event Queue, and the callback is executed by the event loop.

Flow of Operations
1. JS Code executes in the V8 engine.
2. I/O requests (e.g., file read) go through [Link] bindings.
3. libuv handles the async request.
4. If it’s a blocking operation (file read, network call), it goes to the thread pool.
5. When the operation completes, libuv pushes the callback to the Event Queue.
6. The event loop picks it up and executes it in the V8 engine.

5. Thread Pool
• Located inside libuv.
• Used for tasks that cannot be executed asynchronously at the OS level.
• It provides concurrency for CPU-intensive or blocking tasks.
• Default pool size = 4, but can be increased using:
• export UV_THREADPOOL_SIZE=8
6. Evented I/O Flow Example
Let’s visualize the file reading operation in [Link]:
User Code → [Link]('[Link]', callback)

[Link] Bindings → Libuv → Thread Pool (File System thread)

File Read Complete → Event added to Event Queue

Event Loop → Executes callback → V8 Engine → Output
The main thread never gets blocked — other tasks can run simultaneously.

7. Key Advantages of This Architecture


Feature Benefit
Single-threaded Less memory usage, simpler concurrency model
Event loop Handles many requests efficiently
Non-blocking I/O High performance for I/O-heavy applications
Thread pool Parallel execution for heavy tasks
V8 Engine Fast JavaScript execution

8. When to Use [Link]


• Real-time chat applications
• Streaming platforms
• REST APIs / Microservices
• IoT (Internet of Things)
• Single-page applications
Not ideal for:
• CPU-heavy computation (e.g., image processing, data encryption)

Example:
[Link] works like a busy restaurant with one smart waiter (event loop) who handles many customers
efficiently by delegating heavy work (I/O) to the kitchen (libuv) — and everyone gets served quickly
without waiting in line.
Summary Table
Component Role
Application User’s JavaScript code
V8 Engine Executes JavaScript
[Link] Bindings Bridge between JS and C++
libuv Provides event loop and thread pool
Event Loop Manages async operations
Thread Pool Executes blocking operations asynchronously
Event Queue Stores pending callbacks

Advantages & Limitations of [Link]


Advantages
Advantage Explanation
Fast Execution Built on Google’s V8 engine for high speed.
Non-blocking I/O Handles many requests concurrently.
Single Language (JavaScript) Both frontend and backend can use JS.
Scalability Handles a large number of connections efficiently.
Rich Ecosystem (NPM) Thousands of pre-built packages.
Real-time Support Great for chat, live notifications, gaming.

Limitations
Limitation Explanation
Single Threaded Not ideal for CPU-heavy tasks (like image processing).
Callback Hell Complex nesting of async functions can make code hard to
manage.
Less Suitable for Complex Better for I/O bound apps than CPU-bound ones.
Computations
Error Handling Asynchronous code needs careful error handling.
NPM (Node Package Manager)

1. What is NPM & Why Use It?


Definition:
• NPM stands for Node Package Manager — it is the default package manager for [Link].
It helps install, update, manage, and share reusable JavaScript packages or libraries.
• When you install [Link], NPM gets installed automatically.
Purpose:
• To reuse existing code instead of writing everything from scratch.
• To manage project dependencies easily.
• To share your own packages with the community.
• To maintain version control of libraries in your project.
Example scenario:
Imagine you want to hash passwords in your [Link] app.

Instead of writing hashing logic yourself, you can use the NPM package bcrypt.
Install the package
npm install chalk@4
[Link]
// Import the chalk package
const chalk = require('chalk');
// Use chalk to print colored text
[Link]([Link]('Success! Your app is working fine.'));
[Link]([Link]('This is a message in blue.'));
[Link]([Link]('Error: Something went wrong!'));
[Link]([Link]('Warning: Check your input.'));
Run the code: node [Link]

Explanation:
• const chalk = require('chalk'); → imports the installed chalk module.
• [Link](), [Link](), [Link]() → are functions provided by the package to style
console text.
• You didn’t have to write any color logic yourself — just installed and used it via npm.
2. Installing Global & Local Packages
Local Packages
Installed inside your project directory.
They are project-specific and stored in the node_modules folder.
Commands:
1. npm init -y → initialize the project
2. npm install moment → installing the local package
This installs moment locally and adds it to your [Link] under "dependencies".
3. create an [Link] file
// Import moment package
const moment = require('moment');
// Display current date and time
[Link]("Current Date and Time:", moment().format('MMMM Do YYYY, h:mm:ss a'));
// Display formatted date
[Link]("Today is:", moment().format('dddd'));
// Display date after 7 days
[Link]("One week from now:", moment().add(7, 'days').format('MMMM Do YYYY'));
4. Run local_app.js
output:

Explanation:
• npm install moment → installs the package locally.
• It is stored inside the node_modules folder.
• You import it using require('moment') and use it only in this project.

Global Packages
Installed system-wide and can be used in any project or directly from the command line.
Command:
1. npm install -g nodemon → installs nodemon globally on your system.
2. create a file “[Link]”
[Link]("Server is running...");
[Link]("Server restarted successfully!");
[Link]("server has started again!");
3. Run using nodemon
nodemon global_server.js

Explanation:
• Installed with -g → available globally (system-wide).
• Used from the terminal without requiring require() in code.
• Useful for tools, CLIs, and utilities.

3. Initializing a Project (npm init)


Before using npm in a project, you must initialize it.
Command:
npm init
or (for default values)
npm init -y
This creates a file named [Link] which keeps all project-related metadata and dependencies.

4. [Link] & [Link]


[Link]
This file acts as the heart of your project.
It contains:
• Project details (name, version, author, license)
• Scripts (commands like start, test)
• Dependencies (packages your app needs)
• DevDependencies (packages used for development only)
Example [Link]:
{
"name": "myapp",
"version": "1.0.0",
"description": "A demo [Link] app",
"main": "[Link]",
"scripts": {
"start": "node [Link]"
},
"dependencies": {
"express": "^4.18.2",
"mongoose": "~7.2.0"
},
"devDependencies": {
"nodemon": "^3.0.2"
},
"author": "Harismitha",
"license": "ISC"
}
Explanation:
• "scripts" allows custom commands (e.g., npm start runs node [Link]).
• "dependencies" lists runtime libraries.
• "devDependencies" lists tools only needed for development.

[Link]
This file is automatically generated when you install packages.
Purpose:
• Records exact versions of all installed packages.
• Ensures consistent installations across different machines.
• Helps npm install the same dependency tree every time.
Example:
If your [Link] has:
"express": "^4.18.2"
and it installs version 4.18.2,
the [Link] will record that exact version (and dependencies of express) to lock it down.

5. Semantic Versioning
Semantic versioning defines how versions are numbered and updated.
Format:
[Link]
Type Example Meaning
MAJOR 2.x.x Breaking changes
MINOR x.3.x New features (backward compatible)
PATCH x.x.5 Bug fixes (backward compatible)

Version Symbols
Symbol Example Meaning
^ "^4.18.2" Update to latest minor or patch version
(4.x.x)
~ "~4.18.2" Update only patch versions (4.18.x)
None "4.18.2" Use exact version only

Example:
"dependencies": {
"express": "^4.18.2",
"mongoose": "~7.2.0",
"cors": "2.8.5"
}
Explanation:
• express can update to 4.19.0 or 4.20.0 but not 5.0.0
• mongoose can update to 7.2.1, 7.2.2 but not 7.3.0
• cors is fixed at 2.8.5 only.

6. Using NPX
Definition:
npx (Node Package eXecute) is a tool that allows you to run packages without installing them globally.
Example 1 – Running create-react-app:
npx create-react-app myapp
Explanation:
• This runs the create-react-app package temporarily.
• It downloads, runs, and deletes it automatically after execution.
• No need to install globally with npm install -g.

Example 2 – Running local binaries:


If your project has a locally installed tool (like jest):
npx jest
It runs the local version instead of a global one.

Summary Table
Concept Description Example
NPM Node Package Manager npm install express
Local package Installed in current project npm install lodash
Global package Installed system-wide npm install -g nodemon
npm init Initializes a project npm init -y
[Link] Project metadata & dependencies Contains "dependencies"
[Link] Locks dependency versions Auto-created by npm
Semantic versioning Defines update levels ^1.2.3, ~1.2.3, 1.2.3
npx Runs packages without installation npx create-react-app myapp
Node Module System

In [Link], modules are simply reusable blocks of code that are separated into different files. They make
your project modular, organized, and easy to maintain.

1. Local Modules (Create & Use) - Local modules are the ones you create yourself inside your project.
Example: Create and Use a Local Module
1. Create a file: ex1_math.js
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
function multiply(a,b){
return a * b;
}
// Export the functions
[Link] = { add, subtract, multiply };

2. Use the module in another file: ex1_app.js


const math = require('./ex1_math'); // Importing the local module
[Link]("Addition:", [Link](10, 5));
[Link]("Subtraction:", [Link](10, 5));
[Link]("Multiply:", [Link](10, 5));
3. run ex1_app.js

Explanation
• [Link] defines two functions and exports them using [Link].
• [Link] imports them using require('./math').
• The ./ indicates it’s a local file.
• This allows you to organize your project into multiple files.

2. Importing / Exporting (require, [Link])


In [Link], each file is treated as a separate module.
Operation Keyword Example
Export [Link] [Link] = myFunction
Import require() const myFunction = require('./file')

Example 1 — Export a single function


// [Link]
function greet(name) { // [Link]
return `Hello, ${name}!`; const greet = require('./greet');
} [Link](greet("Harismitha"));
[Link] = greet;

Output:

Example 2 — Export multiple values


// [Link]
function add(a, b) {
return a + b; // [Link]
} const { add, multiply } =
require('./mathOperations');
function multiply(a, b) {
[Link](add(3, 4)); // 7
return a * b;
[Link](multiply(3, 4)); // 12
}
[Link] = { add, multiply };
Explanation:
[Link] allows you to expose functions, objects, or variables to other files.
Output:

3. CommonJS (require/[Link]) vs ES Modules (import/export)


[Link] supports two module systems:
Feature CommonJS ES Modules
File Extension .js .mjs or "type": "module" in [Link]
Import syntax const x = require('./file') import x from './[Link]'
Export syntax [Link] = x export default x or export { a, b }
Default in [Link] Yes (CommonJS is default) Optional (modern syntax)

Example: CommonJS (Default)


// [Link]
function greet(name) { // [Link]
[Link](`Hello, ${name}`); const greet = require('./greet');
} greet('hari');
[Link] = greet;

Output:

Example: ES Modules
Add this in your [Link]:
{
"type": "module"
}
Then use:
// [Link] // [Link]
export function greet(name) { import { greet } from './[Link]';
[Link](`Hello, ${name}`); greet('John');
}
Explanation:
• CommonJS is older and synchronous — used by default.
• ES Modules are modern and asynchronous — align with browser standards.
• Both works fine, but ES Modules are now recommended for new projects.

4. Core Modules Overview


[Link] comes with built-in modules — no installation required.
You can import them directly using require() or import.

Common Core Modules


Module Purpose
fs File System (read/write files)
path Handle file paths
os System information (CPU, memory, etc.)
http Create HTTP servers
events Handle event-driven programming

Example 1 — Using fs module


const fs = require('fs');

// Write to a file
[Link]('[Link]', 'Hello from [Link]!');

// Read from a file


const data = [Link]('[Link]', 'utf8');
[Link](data);
Output:
Hello from [Link]!

Example 2 — Using os module


const os = require('os');
[Link]("Operating System:", [Link]());
[Link]("Architecture:", [Link]());
[Link]("Total Memory:", [Link]());
Explanation:
These modules are built into [Link] — no need to install via npm.

Third-Party Modules
Third-party modules are external packages installed from the npm registry.
You install them using:
npm install package-name

Example 1 — Using chalk for colored console output


import chalk from 'chalk'; // (or require('chalk') if using CommonJS)

[Link]([Link]('Success!'));
[Link]([Link]('Error occurred!'));
[Link]([Link]('Warning!'));
Explanation:
• Installed using npm install chalk.
• Makes console output more readable and attractive.

Example 2 — Using nodemon for auto-restart


Install globally:
npm install -g nodemon
Run your project:
nodemon [Link]
Explanation:
Nodemon automatically restarts your app when you make file changes — useful for development.

Summary Table
Module Type Source Installation Example Usage
Local Module Created by you Not needed ./[Link] require('./math')
Core Module Built-in with Not needed fs, os, path, http require('fs')
[Link]
Third-Party npm Registry npm install chalk, nodemon, require('chalk')
Module express
CommonJS Default system Uses Old syntax Compatible
require/[Link] everywhere
ES Modules Modern Uses import/export New syntax More modern and
system async
Core Node Modules

1. path — Working with File Paths


Purpose:
• The path module provides utilities for working with file and directory paths.
• It helps handle paths in a cross-platform way (Windows uses \, Unix uses /).
Import:
const path = require('path');
Common Methods:
Method Description Example
[Link]() Joins path segments [Link]('folder', '[Link]') → 'folder/[Link]'
[Link]() Gets the file name [Link]('/users/test/[Link]') → '[Link]'
[Link]() Gets the file extension [Link]('[Link]') → '.html'
[Link]() Gets directory name [Link]('/users/test/[Link]') → '/users/test'
[Link]() Gives absolute path [Link]('folder', '[Link]')

Example:
const path = require('path');
const filePath = '/users/local/[Link]';
[Link]('Directory:', [Link](filePath));
[Link]('File Name:', [Link](filePath));
[Link]('Extension:', [Link](filePath));
[Link]('Joined Path:', [Link]('folder', 'subfolder', '[Link]'));
Output:
Directory: /users/local
File Name: [Link]
Extension: .txt
Joined Path: folder/subfolder/[Link]

2. os — System Information
Purpose:
• Provides information about the operating system and the computer.
Import:
const os = require('os');
Common Methods:
Method Description
[Link]() OS type (Windows_NT, Linux, etc.)
[Link]() OS platform (win32, linux, darwin)
[Link]() CPU architecture (x64, arm)
[Link]() Total memory (in bytes)
[Link]() Free memory (in bytes)
[Link]() System uptime in seconds
[Link]() System hostname
[Link]() Current user information

Example:
const os = require('os');
[Link]('OS Type:', [Link]());
[Link]('Platform:', [Link]());
[Link]('Architecture:', [Link]());
[Link]('Total Memory:', [Link]());
[Link]('Free Memory:', [Link]());
[Link]('System Uptime (seconds):', [Link]());
[Link]('User Info:', [Link]());

Output (example):
OS Type: Windows_NT
Platform: win32
Architecture: x64
Total Memory: 8388608000
Free Memory: 5120000000
System Uptime (seconds): 12452
User Info: { username: 'admin', homedir: 'C:\\Users\\admin' }

fs — File System Operations


Purpose:
Allows reading, writing, deleting, and managing files and directories.
Import:
const fs = require('fs');
Types of Methods:
1. Synchronous (blocking)
2. Asynchronous (non-blocking, uses callback or promises)

Example 1: Write and Read a File (Synchronous)


const fs = require('fs');
// Write to file
[Link]('[Link]', 'Hello, [Link]!');
[Link]('File written successfully.');
// Read from file
const data = [Link]('[Link]', 'utf8');
[Link]('File content:', data);

Output:
File written successfully.
File content: Hello, [Link]!

Example 2: Write and Read (Asynchronous)


const fs = require('fs');
// Write file asynchronously
[Link]('[Link]', 'This is async write.', (err) => {
if (err) throw err;
[Link]('File written asynchronously.');
// Read file asynchronously
[Link]('[Link]', 'utf8', (err, data) => {
if (err) throw err;
[Link]('File content:', data);
});
});

Output:
File written asynchronously.
File content: This is async write.

Example 3: Using Promises


const fs = require('fs').promises;
async function handleFile() {
await [Link]('[Link]', 'Promise-based file handling');
const data = await [Link]('[Link]', 'utf8');
[Link](data);
}
handleFile();

4. http — Creating a Simple HTTP Server


Purpose:
Used to build a web server that can send and receive HTTP requests/responses.
Import:
const http = require('http');
Example:
const http = require('http');
const server = [Link]((req, res) => {
[Link](200, { 'Content-Type': 'text/plain' });
[Link]('Hello, World! This is a [Link] server.');
});
[Link](3000, () => {
[Link]('Server running at [Link]
});

Output:
Server running at [Link]
Visit: [Link] → You’ll see “Hello, World! This is a [Link] server.”

Example Explanation:
• createServer() → Creates an HTTP server.
• req → Request object (from client).
• res → Response object (to send data to client).
• [Link](200, { 'Content-Type': 'text/plain' }) → Sets HTTP header.
• [Link]() → Sends the response and ends the request.

5. url — Parsing URLs and Query Parameters


Purpose:
Used to parse and handle URLs.
Import:
const url = require('url');
Example:
const url = require('url');
const address = '[Link]
const parsedUrl = [Link](address, true);
[Link]('Host:', [Link]);
[Link]('Pathname:', [Link]);
[Link]('Query:', [Link]);

Output:
Host: [Link]
Pathname: /products
Query: { category: 'books', price: '200' }

Example Explanation:
• [Link](urlString, true) → Parses the URL.
• .host → Returns domain name.
• .pathname → Returns path (/products).
• .query → Returns query parameters as an object.

Summary Table

Module Purpose Example Use


path File and directory path operations Getting file names, extensions
os System and hardware info Checking memory, CPU
fs File read/write Logging, config management
http Web server creation Building APIs, websites
url URL parsing Reading query parameters
Event Handling in [Link]
Event Handling in [Link]
• [Link] is event-driven and non-blocking, making event handling a core part of its architecture.
• The events module provides the EventEmitter class, which is used extensively in [Link] for handling
asynchronous operations, custom events, and built-in modules like HTTP servers.
EventEmitter Class
• The EventEmitter class is the foundation for event handling in [Link].
• It allows objects to emit named events and register listeners (functions) that are called when those
events are emitted.
• Many [Link] built-in modules, such as http, fs, and net, inherit from or use EventEmitter.
Key Methods:
• on(eventName, listener): Registers a listener for the specified event.
• emit(eventName, ...args): Triggers the event, calling all registered listeners with the provided
arguments.
• once(eventName, listener): Registers a listener that is called only once for the event.
• off(eventName, listener): Removes a specific listener.
• removeAllListeners(eventName): Removes all listeners for an event.
• listeners(eventName): Returns an array of listeners for the event.
EventEmitter instances can handle multiple events and listeners, and events are emitted synchronously in the
order listeners were registered.
Registering & Emitting Events
• To use EventEmitter, you first require the events module and create an instance.
• Registering involves attaching callback functions to event names, and emitting triggers those
callbacks.
Example: Basic Registration and Emission
const EventEmitter = require('events');
// Create an EventEmitter instance
const myEmitter = new EventEmitter();
// Register a listener for the 'greet' event
[Link]('greet', (name) => {
[Link](`Hello, ${name}!`);
});
// Emit the 'greet' event with an argument
[Link]('greet', 'Alice'); // Output: Hello, Alice!

Explanation:
• We create an EventEmitter object.
• The on method attaches a listener to the 'greet' event.
• The listener is a function that receives arguments passed during emission.
• emit triggers the event, passing 'Alice' as an argument to the listener.
• If multiple listeners are registered, they all get called in sequence.

You can register multiple listeners for the same event, and they will all fire when the event is emitted.

Example: Custom Events in Node


Custom events are useful for decoupling parts of your application, like notifying when a task completes.

Full Example: Custom Event for User Registration


const EventEmitter = require('events');

class UserRegistration extends EventEmitter {


registerUser(username) {
// Simulate registration logic
[Link](`Registering user: ${username}`);
// Emit a custom event upon success
[Link]('userRegistered', username);
}
}

const registration = new UserRegistration();

// Register listeners for the custom event


[Link]('userRegistered', (username) => {
[Link](`User ${username} has been registered successfully.`);
});

[Link]('userRegistered', (username) => {


[Link](`Sending welcome email to ${username}.`);
});

// Trigger the registration


[Link]('Bob');

Output:
// Registering user: Bob
// User Bob has been registered successfully.
// Sending welcome email to Bob.
Explanation:
• We extend EventEmitter to create a UserRegistration class.
• The registerUser method performs an action and emits a custom 'userRegistered' event with the
username.
• Two listeners are attached: one logs a success message, and the other simulates sending an email.
• When registerUser is called, both listeners are invoked, demonstrating how custom events can trigger
multiple actions.

This pattern is common in libraries for handling asynchronous workflows without tight coupling.

Handling Events in HTTP Server


• [Link]'s http module uses EventEmitter internally. The HTTP server emits events like 'request' for
incoming requests, 'close' when the server closes, and 'error' for errors.

Example: Basic HTTP Server with Event Handling


const http = require('http');

const server = [Link]();

// Handle the 'request' event (emitted for each incoming request)


[Link]('request', (req, res) => {
[Link](200, { 'Content-Type': 'text/plain' });
[Link]('Hello from [Link] HTTP server!\n');
});

// Handle the 'listening' event (emitted when server starts listening)


[Link]('listening', () => {
[Link]('Server is listening on port 3000');
});

// Handle errors
[Link]('error', (err) => {
[Link]('Server error:', err);
});

// Start the server


[Link](3000);

Explanation:
• [Link]() returns an EventEmitter instance.
• The 'request' event is handled to process incoming HTTP requests, sending a simple response.
• 'listening' confirms the server has started.
• 'error' catches any server errors, like port conflicts.
• This shows how events drive the HTTP server's lifecycle, allowing custom handling without blocking
the main thread.
For more complex scenarios, you can emit custom events from within the request handler to notify other parts
of the app.
File System & Streams

The fs module lets you work with files (read/write, create/delete, etc.).

Reading & Writing Files (Sync vs Async)


Example (Synchronous):
const fs = require('fs');
// Write
[Link]('[Link]', 'Hello [Link]!');
// Read
const data = [Link]('[Link]', 'utf-8');
[Link](data);

Explanation:
• writeFileSync() and readFileSync() block execution until the operation completes.
• Useful for small files or initialization.

Example (Asynchronous):
const fs = require('fs');
// Write asynchronously
[Link]('[Link]', 'Hello Async [Link]!', (err) => {
if (err) throw err;
[Link]('File written successfully!');
});
// Read asynchronously
[Link]('[Link]', 'utf-8', (err, data) => {
if (err) throw err;
[Link](data);
});

Explanation:
• [Link]() and [Link]() do not block other code.
• Callback is executed once the operation finishes.

Using [Link]
Example:
const fs = require('fs').promises;

async function fileOps() {


await [Link]('[Link]', 'Learning [Link]');
const data = await [Link]('[Link]', 'utf-8');
[Link](data);
}
fileOps();

Explanation:
• [Link] returns a Promise instead of using callbacks.
• Easier to use with async/await.

Streams in [Link]
What is a Stream?
• A Stream in [Link] is a sequence of data that is read or written continuously over time.
• Instead of reading or writing the whole data at once (like in normal file I/O), streams process data
chunk by chunk, making them efficient for large files or real-time data (e.g., video, audio,
network communication).
• Streams are a core part of [Link] and are implemented using the stream module.

Types of Streams
[Link] has four main types of streams:
Type Description Example
Readable Stream Used to read data Reading files, HTTP request data
Writable Stream Used to write data Writing to files, sending HTTP responses
Duplex Stream Both readable and writable TCP sockets
Transform Stream Modifies or transforms the data zlib compression, crypto encryption

Common Stream Events


Event Description
data Emitted when a chunk of data is available
end Emitted when no more data to read
error Emitted on any error
finish Emitted when all data is written to a writable stream
Example 1: Readable Stream – Reading a File
const fs = require('fs');
// Create a readable stream
const readable = [Link]('[Link]', 'utf8');
// Listen for data events
[Link]('data', (chunk) => {
[Link]('Received chunk:', chunk);
});
// When reading is done
[Link]('end', () => {
[Link]('Finished reading file.');
});

Explanation:
• [Link]() creates a readable stream for [Link].
• The 'data' event is triggered every time a chunk of data is read.
• 'end' is triggered when all data has been read.
• Unlike [Link](), this does not load the entire file into memory — it reads it in parts, making it
efficient for large files.

Example 2: Writable Stream – Writing to a File


const fs = require('fs');

// Create a writable stream


const writable = [Link]('[Link]');

// Write data to the stream


[Link]('Hello, this is the first line.\n');
[Link]('Writing using a stream!\n');

// Close the stream


[Link](() => {
[Link]('Finished writing to file.');
});
Explanation:
• [Link]() creates a writable stream.
• write() adds data chunk by chunk.
• end() signals the end of writing.
• The 'finish' event can be used to confirm completion.

Example 3: Piping – Connect Readable to Writable


const fs = require('fs');

// Read from one file and write to another


const readable = [Link]('[Link]');
const writable = [Link]('[Link]');
// Pipe data directly
[Link](writable);
[Link]('File copied successfully using streams!');

Explanation:
• .pipe() connects the output of one stream to the input of another.
• Data flows automatically from [Link] → [Link].
• It handles backpressure (i.e., not overwhelming the writable stream).

Backpressure:
If the writable stream can’t process data as fast as the readable stream provides it, [Link] automatically
slows down the readable stream. This prevents memory overload.

Buffer in [Link]
What is a Buffer?
• A Buffer is a temporary storage area for raw binary data (bytes).
• It helps [Link] handle binary streams of data (like files, images, or videos).
• Since JavaScript traditionally handles only text (UTF-8 strings), [Link] introduced Buffer to work
with binary data directly.

1. Creating a Buffer
// Create a buffer from a string
const buf = [Link]('Hello World', 'utf-8');
[Link](buf); // <Buffer 48 65 6c 6c 6f 20 57 6f 72 6c 64>
[Link]([Link]()); // Hello World
Explanation:
• [Link]() converts a string into binary data.
• Each pair of hex numbers (48, 65, etc.) represents ASCII codes.
• toString() converts the buffer back to a string.

2. Writing to Buffer
const buf = [Link](20); // Allocate 20 bytes
[Link]('[Link] Streams');
[Link]([Link]());

Explanation:
• [Link](size) creates an empty buffer.
• write() adds data to the buffer.
• Buffers are useful when working with binary or large data chunks.

3. Use Case: Streaming a Video/Audio File


Example: Streaming a Video File to Client
const http = require('http');
const fs = require('fs');
const path = require('path');
[Link]((req, res) => {
const filePath = [Link](__dirname, 'video.mp4');
const stat = [Link](filePath);
const fileSize = [Link];
const range = [Link];
if (range) {
// Parse range header (e.g. "bytes=0-")
const parts = [Link](/bytes=/, "").split("-");
const start = parseInt(parts[0], 10);
const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
const chunksize = end - start + 1;
const file = [Link](filePath, { start, end });
const head = {
'Content-Range': `bytes ${start}-${end}/${fileSize}`,
'Accept-Ranges': 'bytes',
'Content-Length': chunksize,
'Content-Type': 'video/mp4',
};
[Link](206, head);
[Link](res);
} else {
// Send entire file if no range header
const head = {
'Content-Length': fileSize,
'Content-Type': 'video/mp4',
};
[Link](200, head);
[Link](filePath).pipe(res);
}
}).listen(3000, () => {
[Link]('Server running at [Link]
});

Explanation:
• This creates an HTTP server that streams a video file.
• The browser sends a Range header requesting partial data (for fast seek/skip).
• [Link] uses [Link]() to send only the requested chunk of the file.
• The video loads progressively, not all at once.
• This mimics real-world streaming (YouTube, Netflix, etc.).

Summary Table
Concept Description Key Methods
Readable Stream Read data chunk by chunk [Link](), .on('data'), .on('end')
Writable Stream Write data chunk by chunk [Link](), .write(), .end()
Pipe Connect readable → writable .pipe()
Buffer Temporary binary data storage [Link](), [Link](), .toString()
Use Case Efficiently stream media files [Link]() + HTTP server
Error Handling in [Link]

What is Error Handling?


Error handling in [Link] refers to the process of detecting, managing, and responding to errors that occur
during the execution of a program.
Errors can occur due to:
• Invalid user input
• Network issues
• File read/write problems
• Programming mistakes
• Unavailable resources
[Link] uses JavaScript’s try–catch along with its asynchronous callback and Promise-based
mechanisms to handle such errors.

Types of Errors in [Link]


1. Synchronous Errors
These occur immediately during code execution.
They can be caught using try...catch blocks.

Example:
try {
let data = [Link]('Invalid JSON'); // This will throw a SyntaxError
[Link](data);
} catch (err) {
[Link]('Error occurred:', [Link]);
}

Explanation:
• [Link]('Invalid JSON') throws a SyntaxError because the string is not valid JSON.
• The catch block handles it gracefully, so the program doesn’t crash.

2. Asynchronous Errors
These occur later, usually inside callbacks, Promises, or asynchronous functions.
You cannot catch them using a simple try...catch if they are outside the synchronous flow.
Example (fails to catch):
try {
setTimeout(() => {
throw new Error('Async error');
}, 1000);
} catch (err) {
[Link]('Caught error:', [Link]);
}

Output:
Uncaught Error: Async error
Correct way:
Use an error-first callback or Promise .catch() to handle it.

Using try...catch in [Link]


try...catch works best with synchronous code or inside async/await functions.

Example 1: Synchronous
try {
let result = 10 / 0;
[Link]('Result:', result);
} catch (error) {
[Link]('Error:', [Link]);
}

Example 2: Asynchronous (with async/await)


const fs = require('fs').promises;
async function readFileData() {
try {
let data = await [Link]('[Link]', 'utf8');
[Link](data);
} catch (error) {
[Link]('Error reading file:', [Link]);
}
}
readFileData();
Explanation:
• The file doesn’t exist, so [Link]() rejects the Promise.
• The catch block in the async function captures it.

Handling Errors with Callbacks


Before Promises were introduced, [Link] heavily relied on callbacks for async operations.
To maintain consistency, [Link] introduced the Error-First Callback Pattern.

Error-First Callback Pattern


Structure:
function callback(error, result) {
if (error) {
// handle error
} else {
// handle success
}
}

Example:
const fs = require('fs');
[Link]('[Link]', 'utf8', (err, data) => {
if (err) {
[Link]('Error reading file:', [Link]);
} else {
[Link]('File content:', data);
}
});

Explanation:
• If an error occurs (e.g., file not found), err contains the error object.
• If successful, data contains the file content.
• This pattern ensures that errors are handled in the same callback, not thrown unexpectedly.

Global Error Handling


• Sometimes, errors slip through your local handlers and crash the process.
• [Link] provides a way to catch unhandled errors globally to prevent crashes.
1. Handling Uncaught Exceptions
You can listen for uncaught exceptions globally using:

[Link]('uncaughtException', (err) => {


[Link]('There was an uncaught error:', [Link]);
// Do cleanup or logging before exit
[Link](1); // Exit after handling
});
// Example of an unhandled error
throw new Error('Unexpected crash!');

Explanation:
• The [Link]('uncaughtException') listener catches errors not handled elsewhere.
• It logs the error and exits gracefully instead of crashing abruptly.
• However, you should avoid relying only on this, as the application state may be unstable.

2. Handling Unhandled Promise Rejections


When Promises reject without a .catch(), they trigger this event:

[Link]('unhandledRejection', (reason, promise) => {


[Link]('Unhandled Promise Rejection:', reason);
[Link](1);
});
// Example
[Link]('Something went wrong!');

Explanation:
• This is used to catch errors from Promises that weren’t caught with .catch().
• Good practice: Always use .catch() or try...catch with async/await.
Summary Table
Error Type Handling Method Example
Synchronous try...catch JSON parsing, arithmetic errors
Asynchronous (Callback) Error-first callback pattern [Link]()
Asynchronous (Promise) .catch() or try...catch [Link]()
Global uncaught errors [Link]('uncaughtException') Unexpected thrown errors
Unhandled Promise errors [Link]('unhandledRejection') Missing .catch() in Promise
Routing in [Link] (Core http Module)

What is Routing?
• Routing refers to determining how an application responds to a client request to a particular URL
path and HTTP method (GET, POST, PUT, DELETE, etc.).
• In [Link], before using frameworks like Express, you can manually implement routing using the
built-in http module.

1. Setting Up a Basic HTTP Server


Before implementing routes, let’s recall how to create a simple server:
const http = require('http');
const server = [Link]((req, res) => {
[Link](200, { 'Content-Type': 'text/plain' });
[Link]('Welcome to my [Link] server!');
});
[Link](3000, () => {
[Link]('Server running on [Link]
});

Explanation:
• The [Link]() method creates a server.
• req (request) object contains request data (method, URL, headers, etc.).
• res (response) object is used to send data back to the client.

2. Basic Routing (GET, POST, PUT, DELETE)


Routing helps the server respond differently based on:
• The HTTP method ([Link])
• The URL path ([Link])

Example:
const http = require('http');
const server = [Link]((req, res) => {
[Link]('Content-Type', 'application/json');
if ([Link] === '/' && [Link] === 'GET') {
[Link]([Link]({ message: 'Welcome Home!' }));
} else if ([Link] === '/about' && [Link] === 'GET') {
[Link]([Link]({ message: 'About Us Page' }));
} else if ([Link] === '/create' && [Link] === 'POST') {
[Link]([Link]({ message: 'Data Created Successfully' }));
} else if ([Link] === '/update' && [Link] === 'PUT') {
[Link]([Link]({ message: 'Data Updated Successfully' }));
} else if ([Link] === '/delete' && [Link] === 'DELETE') {
[Link]([Link]({ message: 'Data Deleted Successfully' }));
} else {
[Link] = 404;
[Link]([Link]({ error: 'Route not found' }));
}
});
[Link](3000, () => [Link]('Server running at [Link]

Explanation:
• We used [Link] to match the route path.
• We used [Link] to match the HTTP method.
• Different responses are sent for each route.
• If no route matches, it returns a 404 Not Found.

3. Route Parameters ([Link] Parsing)


• Sometimes, you need dynamic routes, such as /users/101 or /products/42.
• Since the core HTTP module doesn’t support route params directly, we manually parse the URL.

Example:
const http = require('http');
const url = require('url');
const server = [Link]((req, res) => {
const parsedUrl = [Link]([Link], true);
const path = [Link]('/');
if (path[1] === 'user' && path[2]) {
const userId = path[2];
[Link](200, { 'Content-Type': 'application/json' });
[Link]([Link]({ message: `User ID received: ${userId}` }));
} else {
[Link](404, { 'Content-Type': 'application/json' });
[Link]([Link]({ error: 'User not found' }));
}
});
[Link](3000, () => [Link]('Server running on [Link]

Explanation:
• /user/101 → splits into ['', 'user', '101']
• Extracted parameter = path[2]
• Server responds dynamically with that value.

4. Query Parameters ([Link])


Query parameters are key-value pairs in the URL after the ? symbol:

Example:
[Link]
• [Link] doesn’t provide [Link] directly (like Express does).
• We can use the built-in url and querystring modules.

Example:
const http = require('http');
const url = require('url');
const querystring = require('querystring');
const server = [Link]((req, res) => {
const parsedUrl = [Link]([Link]);
const query = [Link]([Link]);
if ([Link] === '/search') {
[Link](200, { 'Content-Type': 'application/json' });
[Link]([Link]({ name: [Link], age: [Link] }));
} else {
[Link](404, { 'Content-Type': 'application/json' });
[Link]([Link]({ error: 'Route not found' }));
}
});
[Link](3000, () => [Link]('Server running on [Link]
Explanation:
• [Link]([Link]) extracts the pathname and query string.
• [Link]() converts it into a JavaScript object.
Example:
• /search?name=Alice&age=25
• → { name: 'Alice', age: '25' }
• Response shows parsed values.

5. Handling Different HTTP Methods (GET, POST, PUT, DELETE)


Let’s see how to handle data sent with POST or PUT requests.

Example (Handling Body Data)


const http = require('http');
const server = [Link]((req, res) => {
if ([Link] === '/user' && [Link] === 'POST') {
let body = '';
// Collect data chunks
[Link]('data', chunk => {
body += [Link]();
});
// After receiving all data
[Link]('end', () => {
const parsedBody = [Link](body);
[Link](201, { 'Content-Type': 'application/json' });
[Link]([Link]({ message: 'User Created', user: parsedBody }));
});
} else if ([Link] === '/user' && [Link] === 'GET') {
[Link](200, { 'Content-Type': 'application/json' });
[Link]([Link]({ message: 'Fetching all users...' }));
} else if ([Link] === '/user' && [Link] === 'PUT') {
[Link](200, { 'Content-Type': 'application/json' });
[Link]([Link]({ message: 'User Updated' }));
} else if ([Link] === '/user' && [Link] === 'DELETE') {
[Link](200, { 'Content-Type': 'application/json' });
[Link]([Link]({ message: 'User Deleted' }));
} else {
[Link](404, { 'Content-Type': 'application/json' });
[Link]([Link]({ error: 'Route not found' }));
}
});
[Link](3000, () => [Link]('Server running on [Link]

Example Explanation:
• POST requests may send data in the body (like JSON).
• [Link]('data') collects the incoming chunks.
• [Link]('end') executes after all chunks are received.
• The data is parsed and used in the response.

6. Modular Routing (Manual Router like Express Router)


• In large applications, keeping all routes in one file becomes messy.
• We can manually modularize routes, similar to Express Router.

Example (Manual Router Setup)


File structure:
project/

├── [Link]
└── routes/
├── [Link]
└── [Link]

routes/[Link]
[Link] = (req, res) => {
if ([Link] === '/user' && [Link] === 'GET') {
[Link]([Link]({ message: 'Get all users' }));
} else if ([Link] === '/user' && [Link] === 'POST') {
[Link]([Link]({ message: 'Create new user' }));
} else {
[Link] = 404;
[Link]([Link]({ error: 'User route not found' }));
}
};
routes/[Link]
[Link] = (req, res) => {
if ([Link] === '/product' && [Link] === 'GET') {
[Link]([Link]({ message: 'Get all products' }));
} else if ([Link] === '/product' && [Link] === 'POST') {
[Link]([Link]({ message: 'Create new product' }));
} else {
[Link] = 404;
[Link]([Link]({ error: 'Product route not found' }));
}
};

[Link]
const http = require('http');
const userRoutes = require('./routes/user');
const productRoutes = require('./routes/product');
const server = [Link]((req, res) => {
[Link]('Content-Type', 'application/json');
if ([Link]('/user')) {
userRoutes(req, res);
} else if ([Link]('/product')) {
productRoutes(req, res);
} else {
[Link] = 404;
[Link]([Link]({ error: 'Invalid route' }));
}
});
[Link](3000, () => [Link]('Server running on [Link]

Explanation:
• Routes are separated into different files (modular design).
• The main server imports and delegates routes based on [Link].
• This pattern mimics Express’s Router system but is pure [Link].
Summary Table
Concept Purpose Key Modules Example Route
Basic Routing Handle static routes http /, /about
Route Parameters Handle dynamic URLs url /user/101
Query Parameters Parse query strings url, querystring /search?name=John
Handling Methods Handle GET/POST/PUT/DELETE http /user
Modular Routing Organize routes into separate files require() /routes/[Link]

You might also like