node js theory
node js theory
Node.js ♻️
o What is Node.js ?
Not a language and not a framework it is a Run time environment for
JS
You can run JS outside of the browser - (server)
JavaScript can talk to native machine because of c++
You can create webservers in JavaScript Language
o Why we use Node.js ?
Scalability:
Event driven
Full-Stack Development:
JavaScript is used on both the client and server sides, Node.js enables
full-stack development with a single language, simplifying workflows
for developers
Scalability
Cross-Platform Development
With Node.js, developers can use JavaScript on both the frontend and
backend, simplifying the development process for full-stack
developers.
o Disadvantages of NODE ?
Single-Threaded Nature: Limits performance for CPU-intensive
tasks.
Callback Hell: Can lead to complex and difficult-to-maintain nested
code.
Performance Bottlenecks: Inefficient for heavy computation or
processing tasks.
Error Handling Challenges: Can be complicated in asynchronous
code.
Security Concerns: Vulnerable to common web security issues if not
properly managed.
o Features of NODE ?
o Node Concurrency
o Reactor Pattern
The Reactor Pattern is a design pattern used in Node.js to handle multiple I/O
operations efficiently. It delegates I/O tasks to an event loop and, once these
tasks are completed, invokes the appropriate event handlers asynchronously.
How it Works:
1. Event Loop:
The core of the Reactor Pattern is the event loop, which constantly
listens for I/O events (e.g., file read/write, network requests).
2. Event Demultiplexer:
3. Callbacks:
4. Non-blocking Behavior:
Other operations continue to execute without waiting for the I/O task
to complete, ensuring non-blocking behavior.
Framework
Express.js ㊙️
o What is Express ?
Middleware in Routes:
You can use middleware functions to execute code for specific routes:
Router Module:
A router module is a separate file where you define all your routes,
instead of writing them directly in the main server file. It helps keep
your code clean and organized, especially in larger applications.
app.use('/users', userRouter);
o Router.all ?
How It Works
ts you set up code that will run for all types of HTTP requests to the
/example route.
3. app.all:
When any request (GET, POST, PUT, DELETE, etc.)
goes to /example, app.all runs first.
It logs A request was made to /example.
Then, it calls next() to let the server know to keep
processing the request.
4. app.get and app.post:
If the request was a GET request, app.get handles it
and sends back "This is a GET request."
If the request was a POST request, app.post handles it
and sends back "This is a POST request."
o Alternatives to Express.js (briefly mention other frameworks) ?
Koa.js
Opinionated:
Unopinionated:
Opinionated Unopinionated
Suggest ways to do things different ways to do the same thing
Usually offer a lot of bells & whistles Includes the bare necessities
Strict folder structure Structure folder how you want
o app.use(bodyParser.json())
o Body-parser ?
Body-parser converts the incoming request body sent by the user into a
simple JavaScript object, making it easy to manipulate and access the data
within your application.
Model
Role: Manages data-related logic, representing the data the user
interacts with.
Responsibilities:
Manages data through CRUD (Create, Read, Update,
Delete) operations.
Enforces business rules.
Notifies the View and Controller of any state changes.
Controller
Role: Acts as an intermediary between the View and Model,
handling user input and business logic.
Responsibilities:
Receives and interprets user input.
Updates the Model based on user actions.
Selects and displays the appropriate View.
View
Role: Handles the user interface (UI) logic, presenting data to
the user.
Responsibilities:
Renders data in a specific format for the user.
Displays UI elements.
Updates the display when the Model changes.
o View engines ?
View engines are tools that allow developers to dynamically generate HTML
pages in web applications.
o res.render() vs res.json()
res.json(): Sends a JSON object to the client. The user sees raw
JSON data.
res.render(): Renders an HTML page. The user sees a formatted
web page with HTML elements.
o res.send() vs res.render()
res.send()
res.render
app.locals
Scope: Global across the entire application.
Usage: It is used to store data that is available to all routes and
requests in the application. Data stored here is persistent
throughout the lifetime of the application.
Example: You can set values in app.locals for data or
settings that are globally accessible across all routes.
app.locals.siteName = 'My Awesome App'; // Global
data for the entire app
app.get('/', (req, res) => {
res.send(`Welcome to ${app.locals.siteName}`);
});
Node.js ♻️Architecture ?
o DIAGRAM
fs Module
fs.mkdir : Create a new directory (folder) in the file
system.
Explanation of the Code
fs.mkdir: Creates a new directory
(folder) in the file system.
path.join(__dirname, '/text'):
path.join(): Constructs a file
path from multiple segments,
ensuring compatibility across
platforms (Windows, macOS,
Linux).
__dirname: Global variable
representing the current script's
directory.
'/text': The name of the folder
to be created, located in the
current directory.
Together, path.join(__dirname,
'/text') creates a path to the new 'text'
folder.
Reading a File
**fs.readFile**: Asynchronously
reads file contents.
**path.join(__dirname, 'text',
'Hello.txt')**:
path.join(): Combines path
segments for cross-platform
compatibility.
**__dirname**: Current script's
directory.
**'text'**: Folder containing
the file.
**'Hello.txt'**: The file to
read.
Callback Function:
**err**: Error if reading fails
(e.g., file not found).
**data**: File contents if read
successfully.
Writing to a File
pathModule
Provides utilities for working with file and directory
paths.(for joining, resolving, parsing, formatting,
normalizing and manipulating paths )
Helps handle cross-platform file paths.
different type of path example
// Join paths
const fullPath = path.join('users', 'john',
'document.txt'); // Output:
'users/john/document.txt'
// Resolve an absolute path
const resolvedPath = path.resolve('users',
'john', 'document.txt'); // Outputs absolute
path
// Get the basename of a path
const baseName = path.basename(fullPath); //
Output: 'document.txt'
// Get the directory name
const dirName = path.dirname(fullPath); //
Output: 'users/john'
// Get the file extension
const extName = path.extname(fullPath); //
Output: '.txt'
// Normalize a path
const normalizedPath =
path.normalize('users//john//../john//documen
t.txt'); // Output: 'users/john/document.txt'
// Parse a path into an object
const parsedPath = path.parse(fullPath);
/* Output:
{
root: '',
dir: 'users/john',
base: 'document.txt',
ext: '.txt',
name: 'document'
}
*/
// Check if a path is absolute
const isAbsolutePath =
path.isAbsolute(fullPath); // Output: true or
false
const path = require('path');
const filePath = path.join(__dirname, 'file.txt');
console.log(filePath);
event Module
Provides a way to work with events and event-driven
programming.
Allows you to create and manage event emitters.
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
myEmitter.on('event', () => {
console.log('An event occurred!');
});
myEmitter.emit('event');
os Module
os.platform(): Get the operating system platform
(e.g., 'win32', 'linux').
const os = require('os');
console.log(os.platform()); // e.g., 'win32',
'linux`
os.cpus(): Get information about the CPU(s) in the
system.
const os = require('os');
console.log(os.cpus());
os.freemem(): Get the amount of free memory in
bytes.
const os = require('os');
console.log(os.freemem());
os.totalmem(): Get the total amount of memory in
bytes.
const os = require('os');
console.log(os.totalmem());
os.homedir(): Get the home directory of the current
user.
const os = require('os');
console.log(os.homedir());
url Module
Serialized URL:
//SERIALIZED URL
console.log(myUrl.href);
console.log(myUrl.toString());
Host Information:
myUrl.host returns the host (domain and port).
console.log(myUrl.host);
console.log(myUrl.hostname);
console.log(myUrl.pathname);
console.log(myUrl.search);
Search Parameters:
myUrl.searchParams returns a
URLSearchParams object, allowing for easy
manipulation of the query string.
myUrl.searchParams.append('abc', '123');
console.log(myUrl.searchParams);
You can add parameters using append() and
loop through them with forEach().
myUrl.searchParams.forEach((value, name) => {
console.log(`${name}: ${value}`);
});
Local Modules
Custom modules created for your specific application.
You can define your own functionality and export it for use in
other files.
Third-Party Modules
Modules developed by the community and available through
the npm registry.
Examples: express (web framework), mongoose (MongoDB
object modeling), lodash (utility library).
o Type Of Modules ?
Core modules
These are built-in modules that come with Node.js. They provide
essential functionalities and are available without any additional
installation.
Together, path.join(__dirname,
'/text') creates a path to the new 'text'
folder.
Reading a File
**fs.readFile**: Asynchronously
reads file contents.
**path.join(__dirname, 'text',
'Hello.txt')**:
path.join(): Combines path
segments for cross-platform
compatibility.
**__dirname**: Current script's
directory.
**'text'**: Folder containing
the file.
**'Hello.txt'**: The file to
read.
Callback Function:
**err**: Error if reading fails
(e.g., file not found).
**data**: File contents if read
successfully.
Writing to a File
//SERIALIZED URL
console.log(myUrl.href);
console.log(myUrl.toString());
Host Information:
myUrl.host returns the host (domain and port).
console.log(myUrl.host);
console.log(myUrl.hostname);
console.log(myUrl.pathname);
console.log(myUrl.search);
Search Parameters:
myUrl.searchParams returns a
URLSearchParams object, allowing for easy
manipulation of the query string.
myUrl.searchParams.append('abc', '123');
console.log(myUrl.searchParams);
You can add parameters using append() and
loop through them with forEach().
myUrl.searchParams.forEach((value, name) => {
console.log(`${name}: ${value}`);
});
Local Modules
Third-Party Modules
These are modules developed by the community and available via the
Node Package Manager (NPM)
Model
Role: Manages data-related logic, representing the data the user
interacts with.
Responsibilities:
Manages data through CRUD (Create, Read, Update,
Delete) operations.
Enforces business rules.
Notifies the View and Controller of any state changes.
Controller
Role: Acts as an intermediary between the View and Model,
handling user input and business logic.
Responsibilities:
Receives and interprets user input.
Updates the Model based on user actions.
Selects and displays the appropriate View.
View
Role: Handles the user interface (UI) logic, presenting data to
the user.
Responsibilities:
Renders data in a specific format for the user.
Displays UI elements.
Updates the display when the Model changes.
o npm init ?
npm init is a command used to create a new package.json file for a Node.js
project. This file contains metadata about the project, including its name,
version, dependencies, and scripts.
o Nvm
The package.json file contains project metadata ( information about the project
). For example, project name, version, description, author, license etc.
{
"name": "my-project", // The name of your
project
"version": "1.0.0", // The version of your
project
"description": "A simple Node.js project", // A brief
description of the project
"main": "app.js", // The entry point of
your application
"scripts": { // Scripts that can be
run with npm
"start": "node app.js", // Command to start the
application
"test": "echo \\"Error: no test specified\\" && exit
1" // Command for running tests
},
"keywords": ["node", "express"], // Keywords for
searchability
"author": "Your Name", // The author's name
"license": "MIT", // License type for the
project
"dependencies": { // Packages required for
the application to run
"express": "^4.17.1" // Express framework as
a dependency
},
"devDependencies": { // Packages needed only
during development
"nodemon": "^2.0.4" // Nodemon for auto-
restarting the server during development
}
}
o package-lock.json ?
{
"name": "my-project",
"version": "1.0.0",
"lockfileVersion": 1,
"dependencies": {
"express": {
"version": "4.17.1",
"resolved":
"<https://registry.npmjs.org/express/-/express-4.17.1.tgz>",
"integrity": "sha512-Z0d...",
"dev": false,
"engines": {
"node": ">=0.10.0"
},
"dependencies": {
"body-parser": {
"version": "1.19.0",
"resolved": "<https://registry.npmjs.org/body-
parser/-/body-parser-1.19.0.tgz>",
"integrity": "sha512-...",
"dev": false
}
}
}
}
}
o Scripts in package.json
Scripts in package.json allow you to define custom commands that
automate tasks.
They make it easier to manage and execute common commands (like
starting a server or running tests) with a simple npm run <script-
name>.
HTTP - Middleware - URL
o HTTP Headers ?
HTTP Headers are an important part of the API request and response as they
represent the meta-data associated with the API request and response.
100 Continue: Initial part of a request has been received and the client
can continue with the request.
2xx: Success
200 OK: The request was successful, and the server returned the
requested data.
3xx: Redirection
400 Bad Request: The server cannot process the request due to a client
error (e.g., malformed request syntax).
404 Not Found: The requested resource could not be found on the
server.
408 Request Timeout: The server timed out waiting for the request.
o HTTP Methods ?
Example
// 1. GET: Retrieve data
app.get('/users', (req, res) => {
res.send('List of users');
});
// 2. POST: Send data (create)
app.post('/users', (req, res) => {
res.send('User created');
});
// 3. PUT: Update data (or create)
app.put('/users/:id', (req, res) => {
res.send(`User ${req.params.id} updated`);
});
// 4. DELETE: Remove data
app.delete('/users/:id', (req, res) => {
res.send(`User ${req.params.id} deleted`);
});
// 5. PATCH: Partially update data
app.patch('/users/:id', (req, res) => {
res.send(`User ${req.params.id}'s email updated`);
});
// 6. OPTIONS: Check available methods
app.options('/users', (req, res) => {
res.send('GET, POST, PUT, DELETE, PATCH');
});
GET: When you want to get some data from the server
POST: Send data (create)
PUT: Update data (or create)
DELETE: Remove data
PATCH: Partially update data
OPTIONS: Check available methods
HEAD: Retrieve headers only
o HTTP Options ?
HTTP OPTIONS Method: It's used to find out what HTTP methods
(like GET, POST, PUT, DELETE) are allowed for a particular URL or
endpoint on the server.
Purpose: It helps clients (like browsers or applications) know what
actions they can perform on a specific resource.
o Middleware ?
Example
app.use((req, res, next) => {
console.log("Middleware-1");
res.end("Ending here"); // Ends the request-response
cycle
next(); // This next() is ignored because res.end has
already sent a response
Request Processing: Middleware can handle tasks like logging,
authentication, or parsing request data before reaching the route
handler.
Response Handling: They can modify responses, such as setting
headers or formatting data before sending it back to the client.
Error Handling: Middleware can catch errors during processing.
Error-handling functions take four arguments: (err, req, res,
next).
Chaining: You can chain multiple middleware functions. Each can call
next() to pass control to the next one.
o Morgan
o Middleware Chaining ?
Middleware chaining in Node.js involves executing multiple
middleware functions in sequence for a single request.
Middleware functions process the request object (req), response object
(res), and optionally pass control to the next middleware using
next().
Example:
app.use((req, res, next) => {
console.log('First middleware');
next(); // Passes control to the next middleware
});
app.use((req, res) => {
res.send('Response from second middleware');
});
o URL/URI
URI (Uniform Resource Identifier) identifies a resource either by
location (URL) or by name.
URL (Uniform Resource Locator) is a type of URI that specifies the
location of a resource on the internet.
o URI
For example:
What it is: A web address that tells your browser where to go.
Example: https://example.com/home is a URL that points
to the "home" page of the "example.com" website.
Headers:
What they are: Additional pieces of information sent along
with a web request. They help describe what you want or give
context.
Example: When your browser requests a webpage, it sends
headers that might include:
What type of browser you are using (like Chrome or
Firefox).
What language you prefer for the response.
o URL (Uniform Resource Locator) ?
It is the web address used to access specific resources on the internet
eg: https://example.com/about
o URL encoding ?
URL encoding is like turning your words into a secret code that the internet
can understand.
Conversion: Changes regular text into a special format that uses codes
(like %20 for spaces).
Purpose: This format is used to safely transmit text over the
internet, ensuring that special characters don’t cause confusion.
Example: The phrase "hello world" becomes "hello%20world".
o URL fragment
A URL fragment is the part of a URL that comes after the # symbol. It is
used to point to a specific section or element within a webpage. Fragments are
not sent to the server but are handled by the browser or JavaScript on the
client side.
Example
URL: https://example.com/page.html#section1
Fragment: #section1
It might refer to a section with the ID section1 in the HTML.
Purpose
Example:
const express = require('express');
const app = express();
app.listen(3000);
o app.all() : handles any HTTP method (like GET, POST, PUT, DELETE) for
the same route.
app.all() is used to define a route handler that will handle all HTTP
methods (GET, POST, PUT, DELETE, etc.) for a specific route.
Example:
app.all('/user', (req, res) => {
res.send('Handling all methods for /user');
});
In this example, no matter if the request is a GET, POST, or any other method,
it will go through this route.
Example:
app.set('port', 3000);
app.listen(app.get('port'), () => {
console.log(`Server running on port ${app.get('port')}`);
});
Setting a port:
app.set('port', 3000);
Setting the view engine:
app.set('view engine', 'ejs');
Spawn() vs Fork()
o spawn: Creates a new process to run external commands (like system
commands). Use spawn when you want to run a command that is not
JavaScript (like listing files).
o fork: Creates a new process to run JavaScript code from another file. Use
fork when you want to run another JavaScript file.
o Visual Analogy: Chefs and Kitchens
Using spawn
Using fork
In spawn:
The main chef executes a command in another kitchen (one-
time task).
In fork:
A new chef runs JavaScript code in another kitchen (ongoing
interaction).
o Spawn()
The spawn() method is used to launch a new process with a given command.
It allows you to execute external commands and interact with the child
process’s input and output streams in real time.
Features
Real-time Streaming: spawn() streams data between the
parent and child process in real time, making it suitable for
long-running processes.
Raw I/O: It provides access to raw input and output streams
(stdin, stdout, stderr).
Independent Process: The child process runs independently of
the parent process.
Example
l:
Meaning: Stands for "long format."
Details: Displays detailed information about each file or
directory in the listing.
This includes permissions, number of links,
owner name, group name, file size, last
modification date, and file name.
h:
Meaning: Stands for "human-readable."
Details: Used in conjunction with l to display file sizes
in a more understandable format, such as:
K for kilobytes
M for megabytes
G for gigabytes
For example, instead of showing 2048 for a file size, it
would display 2K.
Roles:
Features:
IPC (Inter-Process Communication): fork() establishes a
communication channel (IPC) between the parent and child
process, allowing for message passing.
Optimized for Node.js: It is optimized for spawning new
Node.js processes, inheriting the environment and execution
context.
Separate V8 Instance: Each forked process has its own V8
instance, making it more isolated.
Example
File: parent.js
File: childScript.js
Roles:
The cluster.fork() method is used in the Node.js Cluster module to create new
worker processes that run the same Node.js application instance. It is typically used to
take advantage of multi-core systems by distributing the workload across multiple
processes.
What is a Port?
o Trace
Tracing is about following the execution path and understanding what
happens during runtime.
Usage: It allows you to specify a directory from which static files can be
served, making it easy to manage and serve client-side resources.
eg: a stream of data over the internet being moved from one computer to
another
eg: a stream of data being in transferred from one file to another within the
same computer
o Duplex stream
Duplex streams enable two-way data flow, making them versatile for
various applications in Node.js.
They handle both reading and writing, allowing for efficient
communication between different parts of your application.
o stream and a duplex stream ?
o Type of Streams
Explained
1.Readable Streams:
Allow reading data from a source.
Data can be consumed piece by piece.
Example: fs.createReadStream() reads data from a
file.
2. Writable Streams:
Allow writing data to a destination.
Data can be written piece by piece.
Example: fs.createWriteStream() writes data to a
file.
3. Duplex Streams:
Allow both reading and writing of data.
Can be used for bi-directional communication.
Example: A TCP socket, where you can both send and
receive data.
4. Transform Streams:
A type of duplex stream that can modify or transform
the data as it is read and written.
Example: zlib.createGzip() compresses data as it is
being read or written.
Readable Streams: Read data from a source.
Writable Streams: Write data to a destination.
Duplex Streams: Read and write data.
Transform Streams: Modify data while reading or writing.
o Asynchronous JavaScript ?
JavaScript is a synchronous, blocking, single-threaded language
This nature however is not beneficial for writing apps
Asynchronous behaviour which is made possible by a browser for FE
and Node.js for backend
o Asynchronous nature of Node JS
Non-blocking IO Model
This is why we use so many callback functions in NODE JS
Callback does not mean asynchronous
o differences between I/O operations and asynchronous programming ?
I/O Operations
o Binary data
Conversion: Turns all kinds of data (like text, images, numbers) into
combinations of 0s and 1s.
Purpose: This format is used inside the computer so that it can
understand and process the information.
Example: The letter "A" becomes 01000001 in binary
o Character set
Events
o Events, Event Emitter, Event Queue, Event Loop, & Event Driven in
Node.js?
Event: A signal that something has happened in a program (e.g., user
interactions, file operations).
Event Emitter: An object that allows you to create and emit events. It
can also listen for events and trigger specific actions when those events
occur.
Event Queue: A queue where emitted events are stored until
they are processed. This ensures that events are handled in the
order they were emitted.
Event Loop: A continuous loop that checks the call stack and event
queue. It picks up events from the event queue and executes their
associated callbacks in the order they were added, ensuring that the
application remains responsive.
Event-Driven: This approach allows the application to respond to
events as they happen, making it efficient for handling I/O operations
and improving scalability.
Event-driven architecture (EDA): it means operation in node are
drive or based by events.
Single threaded
Supports concurrency via events & callbacks
EventEmitter class is used to bind events and listeners
o REPL
Example:
$ node
> 2 + 2
4
> console.log("Hello, World!");
Hello, World!
undefined
Advantages of REPL:
Quick Testing: You can quickly test code snippets without
needing to create a full program.
Learning Tool: It’s useful for beginners to experiment with
JavaScript syntax and Node.js features interactivel
o Overview of how a website works
TCP/IP
1. Import the Events Module: First, you need to import the events
module and create an instance of the EventEmitter class.
2. Create Event Listeners: You can set up functions (listeners) that
respond when specific events occur.
3. Emit Events: You can trigger events using the emit() method.
Routing - Router
o Routing
Routing defines the way in which the clint requests are handled by the
application endpoints.
We can our application to respond to different URLs with different
responses using Routing.
Routing basically means implementing different actions for different
URLs
o Routing in Node.js is done using the built-in http module and requires
manual checking of request URLs.
o
o const http = require('http');
o
o const server = http.createServer((req, res) => {
o if (req.url === '/') {
o res.writeHead(200, {'Content-Type': 'text/plain'});
o res.end('Home'); // Home page response
o } else {
o res.writeHead(404);
o res.end('Not Found'); // 404 response
o }
o });
o
o server.listen(3000, () => {
o console.log('Server running on <http://localhost:3000>');
o });
o Routing in Express provides a cleaner, more intuitive way to define routes,
making it easier to manage web applications.
o const express = require('express');
o const app = express();
o
o app.get('/', (req, res) => {
o res.send('Home'); // Home page response
o });
o
o app.use((req, res) => {
o res.status(404).send('Not Found'); // 404 response
o });
o
o app.listen(3000, () => {
o console.log('Server running on <http://localhost:3000>');
o });
o
o Routing vs Router
Routing
Router
o Router Chaining
Organized Code: Group all related routes for a resource under a single
router.
Avoid Repetition: Avoid repeating the same base path for multiple
routes.
Logical Structure: Helps to maintain a modular route structure.
o Dynamic Routing
o Thread pool
Node.js handles many tasks using a single main thread.
Blocking operations (like reading files) can slow everything down.
A thread pool is a group of helpers that can work on these long tasks.
When a blocking task happens, it’s sent to the thread pool.
The main thread continues to work on other tasks while the helpers
finish the long task.
This keeps the application fast and responsive.
o Tread pool vs Cluster
Cookies are small pieces of data stored on the client’s browser, used for
remembering information across multiple requests or sessions.
In Node.js with Express, a session stores user data (like login info) across
multiple requests. The data stays on the server, and a session ID in a cookie is
sent to the client, helping the server recognize users.
Example
const express = require('express');
const session = require('express-session');
const app = express();
const port = 3000;
// Set up session middleware
app.use(session({
secret: 'mySecretKey', // Secret key to sign session
ID cookie
resave: false, // Avoid saving session if not
modified
saveUninitialized: true // Save uninitialized sessions
}));
// Route to set a session value
app.get('/set-session', (req, res) => {
req.session.user = 'John Doe'; // Store user in
session
res.send('Session set');
});
// Route to get session value
app.get('/get-session', (req, res) => {
const user = req.session.user || 'Guest'; // Get
session data
res.send(`Hello, ${user}`);
});
app.listen(port, () => {
console.log(`Server running on <http://localhost>:$
{port}`);
});
o JWT
JWT (JSON Web Token) is a secure way to share information between two
parties, like a client and a server. It's often used in web applications for user
authentication and authorization.
CORS allows websites to make these requests safely if the other site
explicitly allows it, preventing harmful sites from accessing sensitive
data on your browser.
Steps
Explanation
When a website tries to access resources from another origin (like a different
domain), it first sends a preflight request to the server. This request is
typically an OPTIONS request. The server then responds with an HTTP status
code indicating whether the actual request is allowed or not.
Explanation
1.What Happens:
When a website wants to get information from another
website (different domain), it first sends a preflight
request to check if it’s allowed. This is done using an
OPTIONS request.
2. Server Response:
The server replies with a status code:
200 OK or 204 No Content means the actual
request is allowed.
403 Forbidden or 401 Unauthorized means the
request is not allowed.
3. Why It Matters:
This process keeps cross-origin requests safe and lets
the server control what can be accessed from other
domains.
o CORS and Preflight Requests
CORS (Cross-Origin Resource Sharing) is a security feature
implemented by browsers to control how web pages can request
resources from different origins (domains).
A preflight request is part of the CORS mechanism. It is sent by the
browser before the actual request to check if the server allows the
cross-origin request.
The server responds to the preflight request with HTTP status codes
and headers that indicate whether the actual request is permitted.
o Content-Type
Content-Type tells the server what type of data the client is sending or
expects to receive.
Purpose of Content-Type
Simple Example:
3. Same Origin:
Uses of JSON:
Useful when receiving JSON data from an API or file and you
need to work with it as an object.
Example:
Example:
project-name/
│
├── public/ # For static assets (CSS, JS, images)
│
├── src/
│ ├── routes/ # For app routes
│ ├── controllers/ # For app logic
│ ├── models/ # For database models
│ ├── views/ # For HTML templates
│ └── app.js # Main app entry point
│
└── package.json # Project metadata and dependencies
o Blocking code
Blocking code in programming is any code that stops further execution until a
specific operation completes. This type of code holds up the entire program,
preventing other tasks from running. In the context of Node.js, which is
designed to handle many tasks concurrently, blocking code can reduce
performance since it prevents other operations from continuing until the
current task finishes.
Example:
Example:
Node.js uses a single thread to keep things simple and efficient. It relies on
non-blocking operations and an event loop to handle multiple tasks, which
allows it to manage lots of requests at once without needing extra threads. This
keeps the code simpler and helps prevent errors that come with managing
multiple threads.
o Thread pool
Node.js handles many tasks using a single main thread.
Blocking operations (like reading files) can slow everything down.
A thread pool is a group of helpers that can work on these long tasks.
When a blocking task happens, it’s sent to the thread pool.
The main thread continues to work on other tasks while the helpers
finish the long task.
This keeps the application fast and responsive.
Additional Modules and Tools
o LOCALSTORAGE/SESSIONSTORAGE
o Query Parameters ?
Query parameters are key-value pairs that appear at the end of a URL,
allowing data to be sent to the server as part of the URL itself. They are
typically used in web development to pass additional information in requests,
such as specifying search terms, filters, page numbers, or other variables.
eg:https://example.com/search?query=nodejs&limit=10
o Encryption / Hashing
Encryption transforms data into a coded format, which can be
reversed (decrypted) using a key. Turns readable data into unreadable
cipher text.
Decryption turns the unreadable cipher text back into readable data.
Hashing converts data into a fixed-size string of characters, which
cannot be reversed, typically used for securing passwords.
o Authorization / Authentication
In short, Authentication asks "Who are you?" and Authorization asks "What
can you do?"
o I/O Operations:
I/O operations (Input/Output operations) are tasks that involve getting data
from or sending data to something outside the computer, like reading a file,
sending a request over the internet, or getting input from a user.
console.log('Start');
process.nextTick(() => {
console.log('This runs first in nextTick');
});
console.log('End');
o setImmediate() ?
setImmediate() schedules the callback to run after the current event loop
iteration, but before any timers or I/O events in the next cycle.
It doesn’t wait for all I/O operations or timers that were scheduled in the
current phase to complete.
console.log('Start');
process.nextTick(() => {
console.log('This runs in nextTick');
});
setImmediate(() => {
console.log('This runs in setImmediate');
});
console.log('End');
// Expected Output:
// Start
// End
// This runs in nextTick
// This runs in setImmediate
o Read/write operations
Read Operation: Retrieves data without changing it.
Example: Reading a file, querying a database to get user info.
In code, this might look like:
fs.readFile('data.txt', (err, data) => {
if (err) throw err;
console.log(data);
});
Write Operation: Adds or changes data.
Example: Writing to a file, updating a database record.
In code, this might look like:
fs.writeFile('data.txt', 'Hello World', (err) => {
if (err) throw err;
console.log('Data written!');
});
o Request and response headers ?
Request Headers
Accept: Specifies the media types that the client can process
(e.g., Accept: application/json).
Authorization: Contains credentials for authenticating the
client (e.g., Authorization: Bearer token).
Content-Type: Indicates the media type of the resource being
sent (e.g., Content-Type: application/json).
User-Agent: Provides information about the client software
(e.g., User-Agent: Mozilla/5.0).
Cookie: Contains stored cookies from the client (e.g., Cookie:
sessionId=abc123).
Response Headers
Content-Type: Indicates the media type of the resource being
returned (e.g., Content-Type: application/json).
Cache-Control: Directives for caching mechanisms (e.g.,
Cache-Control: no-cache).
Set-Cookie: Sends cookies from the server to the client (e.g.,
Set-Cookie: sessionId=abc123).
Location: Used in redirection, specifies the URL to redirect
the client to (e.g., Location: <https://example.com>).
Server: Contains information about the server software (e.g.,
Server: Apache/2.4.1).
Request Headers: Sent by the client to provide context about the
request.
Response Headers: Sent by the server to convey information about the
response.
o Dev dependencies vs. dependencies
Dependencies are essential for your application to run in production.
DevDependencies are only necessary during development and testing.
o DNS module
The dns module in Node.js provides functions to interact with the Domain
Name System (DNS), which is how domain names (like example.com) are
translated to IP addresses. This module lets Node.js apps perform DNS
lookups and resolve domain names programmatically.
2. dotenv (Package)
3. process.env (Object)
Example:
6. .env File:
7. PORT=3000
8. DATABASE_URL=mongodb://localhost:27017/myapp
9. Install dotenv Package:
10. npm install dotenv
11. In Your Code:
12. // Load the .env variables
13. require('dotenv').config();
14.
15. // Access them using process.env
16. const port = process.env.PORT; // 3000
17. const dbUrl = process.env.DATABASE_URL; //
mongodb://localhost:27017/myapp
18.
19. console.log(port); // Outputs: 3000
20. console.log(dbUrl); // Outputs:
mongodb://localhost:27017/myapp
Summary:
What It Is: Values in the URL that you define in your route.
Purpose: To capture dynamic information from the URL.
Example: In the route /users/:userId, :userId is a
parameter.
How It Works: If a user visits /users/123, the userId would
be 123.
Accessing It: You can get the value using req.params in
Express:
app.get('/users/:userId', (req, res) => {
const userId = req.params.userId; // This will
be '123'
res.send(`User ID is: ${userId}`);
});
o Query parameter
Definition: Query parameters are used to send additional information
in the URL to the server. They appear after a ? and are separated by &.
Structure:
Example: http://example.com/page?
key1=value1&key2=value2
Here, key1 and key2 are parameter names, while value1 and
value2 are their respective values.
Usage in Express:
You can access query parameters using req.query in an
Express route.
Example:
app.get('/search', (req, res) => {
const searchTerm = req.query.term; // Example: ?
term=apple
const page = req.query.page; // Example: ?page=2
res.send(`Search term is: ${searchTerm}, Page number
is: ${page}`);
});
test
- Run your Express server.
- Access the URL, e.g., `http://localhost:3000/search?
term=apple&page=2`, in your browser or API tool.
Expected Output:
The response will show the captured values: Search
term is: apple, Page number is: 2.
o Libuv
Definition: A multi-platform support library used by Node.js to handle
asynchronous I/O operations. It provides an event-driven architecture
and supports features like networking, file system, and child processes.
Purpose: It abstracts system-specific functionalities (like
asynchronous I/O) across different operating systems (Linux,
Windows, macOS).
o Params - Query - Libvuv
Params: Used to capture dynamic values in the URL path.
Query: Used to send additional data in the URL, typically for filtering
or sorting.
libuv: A library that Node.js uses for non-blocking I/O operations,
making it possible to handle multiple connections simultaneously
without blocking.
o Control flow
Components:
Example:
Purpose: Control flow determines program behavior based on user input and
data states.
o Work flow
Components:
o Summary
Simple Example:
const fs = require('fs');
// Read a file using an error-first callback
fs.readFile('example.txt', 'utf8', (err, data) => {
if (err) {
console.error('Error:', err); // Log the error if
it occurs
return; // Stop the function if there's an error
}
console.log('File content:', data); // Log the file
content if successful
});
o Socket
A socket is a communication endpoint that allows two devices (which
could be a client and a server, or any two devices on a network) to send
and receive messages.
Sockets can use different protocols like TCP or UDP to manage how
data is exchanged.
Used for general network communication, like:
File transfers
Messaging between devices or applications
Network services
o WebSocket
WebSocket is a protocol used for two-way communication
specifically between a client (like a web browser) and a server.
It is designed for real-time data exchange, keeping the connection
open so both the client and server can send messages to each other
without repeatedly reconnecting.
Used for applications like:
Chat apps
Live notifications
Online gaming
WebSocket specifically refers to two-way communication between a
client (like a web browser) and a server.
A Socket can be used for two-way communication between any two
devices on a network, not just a client and server.
o Reactor Pattern
0. Event Demultiplexer:
Continuously checks for events from the demultiplexer and sends them
to the appropriate handler.
2. Handlers (Callbacks):
Functions that process specific events when the reactor signals them.
o PM2
PM2 is a popular, production-grade process manager for Node.js applications.
It helps you manage and keep your Node.js apps alive forever, providing
features for process monitoring, load balancing, and error handling. It’s widely
used to deploy and maintain Node.js applications in production environments.
CRYPTO Module
API 🌐
API (Application Program Interface) ?
o PRACTICAL
Steps:
1. Install Express:
2. npm init -y
3. npm install express
4. Create a file called app.js:
app.listen(port, () => {
console.log(`API is running on <http://localhost>:${port}`);
});
Web API: A type of API specifically designed for web applications, allowing them to
interact over the internet using HTTP requests.
A REST API is a way for different software to communicate over the internet using
standard web methods. It lets you do things like create, read, update, or delete data.
Key points:
o Diagram
o PRACTICAL
o const express = require('express'); // Import Express
o const app = express(); // Create app instance
o const port = 3000; // Set port
o
o app.use(express.json()); // Middleware to parse JSON
o
o // Sample data (items)
o let items = [
o { id: 1, name: 'Item 1' }, // Item 1
o { id: 2, name: 'Item 2' } // Item 2
o ];
o
o // GET: Fetch all items
o app.get('/api/items', (req, res) => {
o res.json(items); // Return all items
o });
o
o // GET: Fetch specific item by ID
o app.get('/api/items/:itemId', (req, res) => {
o const item = items.find(i => i.id ===
parseInt(req.params.itemId)); // Find item
o if (!item) return res.status(404).send('Not found'); // If
not found
o res.json(item); // Return item
o });
o
o // POST: Add new item
o app.post('/api/items', (req, res) => {
o const newItem = { id: items.length + 1, name:
req.body.name }; // Create new item
o items.push(newItem); // Add to array
o res.status(201).json(newItem); // Return new item
o });
o
o // PUT: Update item by ID
o app.put('/api/items/:itemId', (req, res) => {
o const item = items.find(i => i.id ===
parseInt(req.params.itemId)); // Find item
o if (!item) return res.status(404).send('Not found'); // If
not found
o item.name = req.body.name; // Update item name
o res.json(item); // Return updated item
o });
o
o // DELETE: Remove item by ID
o app.delete('/api/items/:itemId', (req, res) => {
o items = items.filter(i => i.id !==
parseInt(req.params.itemId)); // Remove item
o res.status(204).send(); // No content response
o });
o
o // Start server
o app.listen(port, () => {
o console.log(`Server running at <http://localhost>:$
{port}`); // Log server start
o });
Why we use REST API 🌐 ?
o Stateless: Each request is independent, making it easier to scale and manage.
o Standardized Protocols: Uses HTTP methods (GET, POST, PUT, DELETE)
that are widely understood.
o Resource-Based: Focuses on resources (like data) instead of actions, making
it more intuitive.
o Cacheable: Responses can be cached, improving performance.
o Uniform Interface: Simplifies interaction between clients and servers,
enhancing usability.
API vs REST API ?
Feature API 🌐 REST API 🌐
Type of API that follows REST
Interface that allows
Definition (Representational State Transfer)
software to communicate.
architecture.
Can use multiple protocols
Protocol Uses HTTP protocol specifically.
(e.g., SOAP, RPC).
Follows REST architecture principles
Architecture Varies, can be custom.
(stateless, resource-based).
Supports multiple formats Typically uses JSON or XML for data
Data Format
(e.g., XML, JSON). exchange.
State Always stateless; each request is
Can be stateful or stateless.
Management independent.
May or may not support
Caching Built-in support for HTTP caching.
caching.
For general communication Best for web services and client-server
Use Case
between systems. interactions.