0% found this document useful (0 votes)
7 views15 pages

Angular and TypeScript Concepts Explained

The document discusses various concepts related to Angular, TypeScript, Express.js, Node.js, and MongoDB, including lazy loading, dependency injection, and middleware. It also covers testing strategies for Angular applications, the event loop in Node.js, and security measures against XSS and CSRF attacks. Additionally, it provides a sample Node.js program for saving a document in MongoDB using Mongoose.

Uploaded by

rohitmakhare2002
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)
7 views15 pages

Angular and TypeScript Concepts Explained

The document discusses various concepts related to Angular, TypeScript, Express.js, Node.js, and MongoDB, including lazy loading, dependency injection, and middleware. It also covers testing strategies for Angular applications, the event loop in Node.js, and security measures against XSS and CSRF attacks. Additionally, it provides a sample Node.js program for saving a document in MongoDB using Mongoose.

Uploaded by

rohitmakhare2002
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

a) Define lazy loading in Angular.

Lazy loading is a design pattern that loads NgModules, components, and assets only when
they are needed, typically when a user navigates to a specific route. This contrasts with
eager loading, where everything is loaded at the initial launch of the application.
* Benefit: Improves the application's initial load time by keeping the initial bundle size small,
enhancing the user experience.

b) What is the role of dependency injection in Angular?


Dependency Injection (DI) is a core design pattern in Angular used to provide components
with the services or dependencies they need.
* Role: Angular's DI framework injects an instance of a dependency (a service) into a
dependent object (a component or another service) instead of the dependent creating it
itself. This promotes decoupling, reusability, and makes code easier to test (mocking
dependencies).

c) How does TypeScript enforce type safety in Angular applications?


TypeScript (TS) is a superset of JavaScript that adds static typing.
* Type Annotation: You can explicitly define data types for variables, function arguments,
and return values (e.g., let name: string = "Alice";).
* Compile-Time Check: TS checks for type compatibility before the code runs (at compile
time). If a type mismatch is found, it throws an error, preventing a common class of runtime
bugs that might occur in pure JavaScript.

d) What is Mongoose in MongoDB?


Mongoose is an Object Data Modeling (ODM) library for [Link] and MongoDB.
* Role: It provides a schema-based solution to model your application data. It handles the
relationship between data, provides schema validation, and is used to translate objects in
code to documents in MongoDB, making it easier to interact with the database using
object-oriented methods.

e) What is MongoDB Atlas?


MongoDB Atlas is a fully managed cloud database service offered by MongoDB.
* Features: It allows developers to deploy, operate, and scale MongoDB databases in the
cloud (AWS, Google Cloud, Azure) without managing the underlying infrastructure. It
includes built-in features for backup, recovery, monitoring, and security.

f) What is body parsing in [Link]?


Body parsing is the process of extracting data submitted in the body of an incoming HTTP
request (e.g., in a POST or PUT request).
* Mechanism: [Link] uses middleware (like [Link]() or [Link]()) to
read the request body, convert it from formats like JSON or URL-encoded form data into a
JavaScript object, and then attach it to the [Link] property for easy access in your route
handlers.

Q2) Attempt the following:


a) i) What is the purpose of @Input() and @Output() in Angular? [2]
* @Input() (Data In): A decorator used to mark a property in a child component as a target
for a data binding from its parent component. It allows data to flow down from parent to child.
* @Output() (Event Out): A decorator used to mark a property in a child component as an
event emitter. It allows the child component to emit custom events that the parent
component can listen to and respond to. It facilitates communication up from child to parent.

a) ii) Write a note on core concepts of RxJS. [4]


RxJS (Reactive Extensions for JavaScript) is a library for composing asynchronous and
event-based programs using Observables.
| Concept | Description |
|---|---|
| Observable | Represents a future stream of data or events. It's a producer of multiple
values over time. It is lazy—it won't execute until someone subscribes. |
| Observer | A consumer of values delivered by an Observable. It's an object with three
methods: next() (to handle the emitted value), error() (to handle errors), and complete() (to
notify the stream is finished). |
| Subscription | The result of calling [Link](observer). It links an Observable
to an Observer. It is primarily used to unsubscribe and clean up resources, preventing
memory leaks. |
| Operators | Pure functions that allow declarative manipulation of data streams. They take
an Observable as input and return a new Observable. Examples include map, filter,
debounceTime, switchMap, etc. |

b) Explain the purpose of following Angular lifecycle hooks: [4]

Angular components and directives have a lifecycle managed by Angular. The following are
key lifecycle hooks:
* i) ngOnChanges:
* Purpose: Called before ngOnInit and whenever one or more data-bound input properties
(@Input() properties) of the component/directive change.
* Use Case: Performing logic based on changes to an input value (e.g., re-calculating
internal state). It receives a SimpleChanges object containing the current and previous
values.
* ii) ngOnInit:
* Purpose: Called once after the component's input properties have been checked and
initialized. It is typically the standard location for component initialization tasks.
* Use Case: Initializing data, fetching data from a remote service, or setting up complex
component state.
* iii) ngDoCheck:
* Purpose: Called immediately after ngOnChanges and ngOnInit, and then during every
subsequent change detection run.
* Use Case: Detecting and acting upon changes that Angular's default change detection
mechanism might not catch (e.g., changes to objects or arrays inside the component). It is
resource-intensive and should be used cautiously.
* iv) ngAfterContentInit:
* Purpose: Called once after Angular has projected external content into the component's
view via <ng-content>.
* Use Case: Used to initialize content that has been projected and is available for the first
time.

a) i) Define code splitting in web development. [2]

Code splitting is a technique in modern web build tools (like Webpack or Vite) that breaks a
single, large JavaScript bundle into multiple smaller chunks.
* How it works: These chunks are loaded on demand. For example, the core application
logic is loaded initially, and code for specific routes, modules, or features is only loaded
when the user accesses them (often via Angular's lazy loading).
* Benefit: Reduces the initial loading time by minimizing the size of the JavaScript payload
that must be downloaded and parsed on application startup.
a) ii) What are utility types in TypeScript? Explain Conditional Type (any four). [4]
Utility Types are pre-built type aliases in TypeScript that make common type transformations
easier, helping to create new types based on existing ones.
* 1. Partial<Type>:
* Purpose: Constructs a type with all properties of Type set to optional.
* Use Case: When defining a function that takes an object with optional parameters that
match a full interface.
* 2. Readonly<Type>:
* Purpose: Constructs a type with all properties of Type set to readonly, meaning the
properties of the constructed type cannot be reassigned after they are created.
* Use Case: To ensure immutability of an object's properties.
* 3. Pick<Type, Keys>:
* Purpose: Constructs a type by selecting a set of properties (Keys) from Type.
* Use Case: To create a new type that is a subset of an existing interface.
* 4. Omit<Type, Keys>:
* Purpose: Constructs a type by taking all properties from Type and then removing Keys.
* Use Case: To create a new type that excludes certain properties from an existing
interface.
Conditional Types:
A conditional type has the form T extends U ? X : Y. If the type T is assignable to type U,
then the type is X; otherwise, the type is Y. They are fundamental for creating advanced
utility types.

b) What are decorators in TypeScript? Provide an example of using a class decorator. [4]

Decorators are a special kind of declaration that can be attached to classes, methods,
accessors, properties, or parameters. They are functions that execute at declaration time
and can be used to modify or annotate the declaration they are attached to.
* Syntax: They are denoted by the @expression syntax, where expression evaluates to a
function that will be called at runtime.
* Role: Decorators are a key part of frameworks like Angular (e.g., @Component,
@Injectable) for adding metadata and behavior to classes.
Example: Class Decorator
// 1. The Decorator Factory (a function that returns the decorator)
function LogClass(constructor: Function) {
[Link](`Class ${[Link]} was instantiated.`);
// You could also add new properties or methods here
}

// 2. Applying the Decorator


@LogClass
class UserService {
private users: string[] = ['Alice', 'Bob'];

getUsers() {
return [Link];
}
}

// When the UserService class is defined, the LogClass function runs,


// and the message "Class UserService was instantiated." is logged to the console.

Q4) Attempt the following:

a) i) Explain the concept of middleware in [Link]. [2]


Middleware in [Link] refers to functions that have access to the request object (req), the
response object (res), and the next middleware function in the application's
request-response cycle (next).
* Function: They can execute any code, modify the request and response objects, end the
request-response cycle, or call the next middleware function.
* Use Case: Performing common tasks across multiple routes, such as:
* Authentication checks (e.g., verifying a JWT).
* Logging and monitoring.
* Body parsing ([Link]()).
* Data validation.
a) ii) How does non-blocking I/O work in [Link]? [4]
[Link] operates on a single-threaded Event Loop model, which is key to its high
performance and scalability through non-blocking I/O (Input/Output).
* Non-Blocking Nature: When [Link] encounters an I/O operation (like reading a file,
querying a database, or making an HTTP request), it does not wait for the operation to
complete. Instead, it delegates the I/O task to the operating system (or a worker thread) and
immediately moves on to processing the next request in the queue.
* The Event Loop: The main thread keeps spinning in the Event Loop. When the I/O
operation finishes, it places a callback function (the code that handles the result) onto the
Event Queue.
* Callback Execution: Once the main call stack is empty, the Event Loop pulls the callback
from the queue and executes it on the single thread.
This mechanism ensures the single thread is never idle waiting for slow I/O, allowing [Link]
to handle a huge number of concurrent requests efficiently.

b) Discuss in details working of event loop in [Link]? [4]


The Event Loop is the core mechanism that allows [Link] to perform non-blocking I/O
operations despite being single-threaded. It is a continuous cycle, divided into distinct
phases, each handling a specific type of callback queue:
* Timers Phase: Executes callbacks scheduled by setTimeout() and setInterval().
* Pending Callbacks Phase: Executes callbacks for some operating system operations, like
handling TCP errors.
* Idle, Prepare Phase: Used internally by [Link].
* Poll Phase (Wait for I/O):
* Retrieves new I/O events (e.g., file read completion, network request data).
* If there are timers scheduled, the loop will exit the poll phase to check timers.
* Otherwise, it will wait for new events.
* Check Phase: Executes callbacks scheduled by setImmediate().
* Close Callbacks Phase: Executes callbacks for resource closing, such as
[Link]('close', ...) handlers.
Microtask Queues (Priority Queue):
Between each main phase, [Link] checks and drains two higher-priority queues:
* [Link]() queue: Handled first, even before the timer phase.
* Promise Microtask queue: Handles then(), catch(), and finally() callbacks for resolved
promises.
This cyclical and phased execution is what keeps [Link] responsive and asynchronous.

a) What are the Testing Strategies used for AngularJS Application? [5]

While the question specifies AngularJS (the older framework), the current standard in the
full-stack context is modern Angular. Assuming the intent is for modern Angular, the key
testing strategies are:
* Unit Testing:
* Focus: Testing isolated pieces of code, primarily services, pipes, and small components,
often without the UI rendering.
* Tools: Jasmine (testing framework) and Karma (test runner).
* Goal: To ensure individual classes and functions work as expected. Services are tested
by mocking their dependencies. Components are tested using the TestBed utility to check
their logic and template interactions.
* Integration Testing:
* Focus: Testing how different parts of the application work together (e.g., a component
interacting with a service, or a series of pipes working in a template).
* Tools: Still uses TestBed but involves configuring modules and providing real (or mock)
dependencies to ensure the components and services integrate correctly.
* End-to-End (E2E) Testing:
* Focus: Simulating a real user's workflow in a browser to test the entire application, from
UI to database.
* Tools: Protractor (historically for Angular) or modern alternatives like Cypress or
Playwright.
* Goal: To ensure the whole application functions correctly from a user's perspective (e.g.,
"Can a user log in, add an item to the cart, and checkout?").
* Snapshot Testing:
* Focus: Capturing the rendered output (e.g., the HTML structure) of a component and
comparing it against a stored "snapshot" to detect unintended UI changes.
* Tools: Often integrated with Jest.

b) Write a NodeJS program that saves a document in MongoDB using mongoose. [5]

This example demonstrates a basic [Link] application using Express and Mongoose to
connect to a MongoDB database and save a new user document.
// 1. Setup - Import necessary modules
const express = require('express');
const mongoose = require('mongoose');
const app = express();
const PORT = 3000;

// Use [Link]() middleware for parsing JSON request bodies


[Link]([Link]());

// 2. Connect to MongoDB (Replace with your actual connection string)


const dbURI = 'mongodb://localhost:27017/mydatabase';
[Link](dbURI)
.then(() => [Link]('MongoDB Connected successfully!'))
.catch(err => [Link]('MongoDB connection error:', err));

// 3. Define the Mongoose Schema


const userSchema = new [Link]({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
age: Number
});

// 4. Create the Mongoose Model


const User = [Link]('User', userSchema);

// 5. Define the Express Route to Save a Document


[Link]('/api/users', async (req, res) => {
try {
// Create a new User instance from the request body
const newUser = new User([Link]);

// Save the document to the database


const savedUser = await [Link]();
// Respond with the saved document
[Link](201).json({
message: 'User saved successfully!',
user: savedUser
});
} catch (error) {
// Handle validation or database errors
[Link](400).json({
error: 'Could not save user',
details: [Link]
});
}
});

// 6. Start the server


[Link](PORT, () => {
[Link](`Server is running on [Link]
});

/*
To test this:
Send a POST request to [Link] with a JSON body:
{
"name": "Jane Doe",
"email": "[Link]@[Link]",
"age": 28
}
*/

c) Explain the Need for security in Angular and XSS, CSRF prevention. [5]

Need for Security in Angular Applications:


The client-side nature of Angular applications, which often communicate with backend APIs
via REST, makes them vulnerable to attacks. Security is crucial to protect user data,
maintain application integrity, and ensure compliance. Key needs include preventing:
* Data Theft: Protecting credentials and sensitive user information.
* Session Hijacking: Preventing attackers from taking over a user's active session.
* Content Injection: Ensuring malicious scripts are not executed in the user's browser.
Specific Threat Mitigation
1. Cross-Site Scripting (XSS) Prevention
XSS attacks occur when an attacker successfully injects malicious client-side scripts (usually
JavaScript) into a web page viewed by other users.
* Angular Prevention Strategy:
* Automatic Sanitization (Default): Angular treats all values as untrusted by default. When
binding a value (e.g., via property binding, interpolation), Angular automatically sanitizes the
value before inserting it into the DOM. This involves stripping out potentially malicious code
like <script> tags.
* Contextual Security: Angular's sanitizer is contextual. It uses different rules based on
where the data is being used (e.g., HTML, style, URL).
* DomSanitizer: For cases where a value must be included without sanitization (e.g., a
trusted piece of HTML), developers must explicitly bypass security using the DomSanitizer
service and its bypassSecurityTrust* methods, which serves as an explicit security sign-off.

2. Cross-Site Request Forgery (CSRF) Prevention

CSRF attacks trick an authenticated user's browser into sending a request to a website that
changes state (e.g., transfers money, changes a password) without the user's knowledge.
* Angular/Backend Prevention Strategy:
* SameSite Cookie Policy: The most modern defense, where cookies are only sent with
requests originating from the same site.
* Anti-Forgery Tokens (Synchronizer Token Pattern): The common defense for
Angular/REST APIs:
* The server sends a unique, unpredictable CSRF token to the client (e.g., in a cookie or
header).
* The client (Angular) reads this token.
* For every state-changing request (POST, PUT, DELETE), the client must send the token
back to the server, often in a custom HTTP header (e.g., X-CSRF-Token).
* The server compares the token in the header/body with the token it originally issued. If
they don't match, the request is rejected. Since the attacker's fraudulent site cannot read the
token from the user's domain, the request will fail.

Q1) Solve Any Five of the following: [5 x 1 = 5]


a) What is an Observable in RxJS?
An Observable is a core concept in RxJS that represents a stream of values over time. It is a
producer of multiple values, asynchronously or synchronously.
* Key Feature: Observables are lazy. They will not start emitting values until an Observer
explicitly subscribes to them.

b) What are utility types in TypeScript?

Utility Types are built-in type aliases provided by TypeScript that simplify common type
transformations. They allow you to easily create new types by manipulating or composing
existing types (e.g., making all properties optional, picking specific properties, etc.).
c) Which middleware is used in [Link] to parse JSON request bodies?
The middleware used is [Link](). This built-in middleware function parses incoming
requests with JSON payloads and populates the [Link] property with the resulting
JavaScript object.

d) What does the populate() method do in Mongoose?

The populate() method in Mongoose is used for referencing data across different collections.
It automatically replaces specified paths (fields) in a document with the actual document(s)
from other collections, effectively performing a JOIN operation that is common in relational
databases.

e) List the tool for unit testing in web applications.

The primary toolset for unit testing in modern web applications (like Angular) is:
* Jasmine (Testing framework/syntax).
* Karma (Test runner environment).
* Jest (An alternative, popular all-in-one framework).

f) Define lazy loading in Angular.

Lazy loading is an architectural pattern in Angular where modules and their components are
loaded on demand (only when the user navigates to the associated route), rather than being
loaded at the initial startup of the application. This significantly improves the initial load time.

Q2) Attempt the following: [10]

a) i) What is Advanced Routing? Explain its types. [2]

Advanced Routing in modern web frameworks (like Angular) refers to routing configurations
that go beyond simple, static path matching. It includes features that enable complex,
dynamic, and efficient navigation schemes.
* Types of Advanced Routing:
* Lazy Loading: Loading modules only when the user navigates to a specific route,
improving initial load performance.
* Child (Nested) Routes: Defining routes that are relative to a parent component, allowing
components to have their own mini-router outlets.
* Route Guards: Logic (functions/classes) executed before or during navigation to control
access (e.g., ensuring a user is logged in before accessing an admin page).
* Route Resolvers: Logic executed before a route component is activated, ensuring
required data is fetched and available before the component loads.

a) ii) Demonstrate generic principles in TypeScript with suitable example. [4]


Generics are tools that allow you to create reusable components that can work with a variety
of data types, while maintaining type safety. They define a type variable that is linked to a
component (function, class, or interface).
Generic Principle: The component receives the type variable as an argument, and its internal
functions and properties use that variable, making the component type-agnostic until it is
called.
Example: A function that returns the first element of an array, regardless of the element type.
// Without Generics (Uses 'any' and loses type information)
function getFirstElement_Any(arr: any[]): any {
return arr[0];
}

// With Generics (The <T> acts as a type variable)


function getFirstElement_Generic<T>(arr: T[]): T {
// The input is an array of T, and the return type is T
return arr[0];
}

// Usage Example 1 (Type T is inferred as 'string')


let strings = ['apple', 'banana', 'cherry'];
let firstString = getFirstElement_Generic(strings);
// TypeScript knows firstString is of type 'string'

// Usage Example 2 (Type T is inferred as 'number')


let numbers = [10, 20, 30];
let firstNumber = getFirstElement_Generic(numbers);
// TypeScript knows firstNumber is of type 'number'

// Benefit: We write one function that safely handles any array type.

b) Explain Data encryption at rest and in transit in the context of mongoDB. [4]
Data security in MongoDB requires protection in two primary states:
| State | Context & Technology | Explanation |
|---|---|---|
| At Rest (Stored Data) | Context: Data stored on physical disks. Technology: WiredTiger
Storage Engine Encryption (MongoDB Enterprise/Atlas). | This involves encrypting the actual
data files on the server's file system using algorithms like AES-256 (Advanced Encryption
Standard). Even if an unauthorized party gains access to the physical disk files, they cannot
read the data without the encryption key. |
| In Transit (Data Transfer) | Context: Data moving between the client application (e.g.,
[Link] server) and the MongoDB database server. Technology: TLS/SSL (Transport Layer
Security/Secure Sockets Layer). | MongoDB strongly recommends using TLS/SSL to encrypt
all network traffic. This ensures that any data packets intercepted during transmission are
scrambled and unreadable, preventing Man-in-the-Middle (MITM) attacks. |

Q3) Attempt the following: [10]

a) i) Explain the difference between promises and async/await in [Link]. [2]

Both Promises and async/await are used in [Link] for handling asynchronous operations,
but they differ in syntax and readability.
| Feature | Promises | Async/Await |
|---|---|---|
| Syntax | Uses .then() for success and .catch() for errors, leading to chaining (potential
"callback hell" if misused). | Uses the await keyword within an async function, making
asynchronous code look and behave like synchronous code. |
| Readability | Can be difficult to read and maintain when many asynchronous steps are
involved. | Offers a much cleaner, linear, and more readable style, simplifying complex
asynchronous logic. |
| Error Handling | Uses .catch() or a second argument to .then(). | Uses standard JavaScript
try...catch blocks, which is familiar and intuitive. |
a) ii) Explain authentication and authorization in a database context of mongoDB. [4]
| Concept | Definition in MongoDB | Implementation |
|---|---|---|
| Authentication | Verification of Identity. Proving that a user or application client is who they
claim to be before accessing the database. | MongoDB typically uses: 1.
Username/Password: Stored securely (hashed) within the database's administrative tables.
2. X.509 Certificates: For more secure client-server authentication. 3. LDAP/Kerberos:
Integration with enterprise directories. |
| Authorization | Defining Permissions. Determining what an authenticated user or client is
allowed to do (e.g., read, write, update, delete) on which databases or collections. |
MongoDB uses a Role-Based Access Control (RBAC) system. Users are assigned one or
more roles (e.g., read, readWrite, dbAdmin). These roles define the specific privileges they
have on a given resource (database or collection). |
b) Explain State management with NgRx. [4]
NgRx is a group of libraries inspired by the Redux pattern, used for predictable state
management in large-scale Angular applications.
State Management Goal: To move the application's shared data (state) out of individual
components and into a single, centralized store, ensuring all components read from a single
source of truth.
Core Principles/Concepts:
* Store: The single source of truth. It holds the entire application state as a single immutable
object.
* Action: An object that describes what happened (e.g., [User] Login Success). They are
dispatched from components.
* Reducer: A pure function that takes the current State and an Action, and returns a new,
immutable State. It is the only way the state can be changed.
* Effect: Handles side effects (like fetching data from a backend API). Effects listen for
actions, execute asynchronous tasks, and then dispatch new actions (e.g., a "Login Failed"
action or a "Data Fetched" action) to be handled by a Reducer. 5. Selector: Pure functions
used by components to efficiently read and derive specific slices of data from the State.

Q4) Attempt the following: [10]

a) i) Explain HTTPS. [2]

HTTPS (Hypertext Transfer Protocol Secure) is an extension of HTTP that adds a layer of
security using the TLS/SSL (Transport Layer Security/Secure Sockets Layer) protocol.
* Function: It encrypts the communication between the client's web browser and the server,
protecting data integrity and confidentiality.
* Key Benefit: Prevents eavesdropping and tampering with data (e.g., passwords, credit
card numbers) as it travels across the network.
a) ii) Explain schema validation and middleware in Mongoose with example. [4]
| Concept | Description | Example (Conceptual) |
|---|---|---|
| Schema Validation | The process of ensuring that data written to the MongoDB database
conforms to the structure and rules defined in the Mongoose Schema. | Example: Defining
that the age field must be a Number and must be greater than 18. If a client attempts to save
a string or an age of 15, Mongoose validation middleware will throw an error before the
operation is sent to MongoDB. |
| Mongoose Middleware (Hooks) | Functions (also called hooks) that are executed at specific
phases of the document's life cycle (e.g., validate, save, remove, find). | Example: A
pre('save') hook can be used to hash a user's password before it is saved to the database.
The hook executes, modifies the document, and then calls next() to proceed with the save
operation. |
Mongoose Middleware Example (pre hook):
// In your User Schema definition:
[Link]('save', function(next) {
const user = this;
// Only hash the password if it has been modified or is new
if (![Link]('password')) return next();

// Use a hashing library (like bcrypt) to hash the password


[Link]([Link], saltRounds, (err, hash) => {
if (err) return next(err);
[Link] = hash; // Replace plain text password with hash
next(); // Proceed to the actual save operation
});
});

b) What is middleware in [Link], and how is it used for request processing and error
handling? [4]

Middleware in [Link] is a function that sits between the request being received and the
final route handler. It has access to the request (req), response (res), and the next
middleware function (next).
1. Request Processing:
* Middleware is chained together and executed sequentially.
* It performs common tasks like logging, authentication, and parsing the body.
* Example: [Link]([Link]()) parses the body, and an authentication middleware can
check a token:
<!-- end list -->
// Request Processing Middleware
const authenticate = (req, res, next) => {
if ([Link] === 'valid-token') {
next(); // Allow request to proceed to the next handler
} else {
[Link](401).send('Unauthorized'); // Stop the cycle
}
};
// Route uses the middleware before the final logic
[Link]('/admin', authenticate, (req, res) => { /* ... */ });

2. Error Handling:
* Express uses a special type of middleware for error handling, which accepts four
arguments: (err, req, res, next).
* When an error occurs in any preceding middleware or route handler, next(error) is called,
skipping all remaining regular middleware and jumping straight to the error-handling
middleware.
<!-- end list -->
// Error Handling Middleware (must have 4 arguments)
[Link]((err, req, res, next) => {
[Link]([Link]); // Log the error
[Link](500).send('Something broke!'); // Send a standard error response
});

Q5) Attempt any two of the following: [10]

a) Explain the concept of custom life-cycle hooks in Angular. [5]

Angular's built-in lifecycle hooks (ngOnInit, ngOnChanges, etc.) are sufficient for most
component logic. Custom life-cycle hooks are essentially just services or reusable functions
that encapsulate common logic and hook into the standard Angular lifecycle using
dependency injection.
Purpose of Custom Hooks:
* Reusability: Encapsulate complex or repetitive logic so it can be reused across multiple
components.
* Cleaner Components: Move side effects and lifecycle logic out of the component class,
making the component smaller, focused, and easier to read.
Implementation (via Service/Function):
A common way to create a "custom hook" is by defining an injectable service that uses the
Angular OnDestroy hook to perform cleanup.
Example: [Link] (Custom logging hook)
import { Injectable, OnDestroy, OnInit } from '@angular/core';

@Injectable({ providedIn: 'root' })


export class UseLoggerService implements OnInit, OnDestroy {
private componentName: string = '';

// Initialize the hook with the component name


init(name: string) {
[Link] = name;
[Link](); // Explicitly call the desired hook
}

ngOnInit() {
[Link](`[${[Link]}] Component Initialized.`);
}

ngOnDestroy() {
[Link](`[${[Link]}] Component Destroyed. Cleaning up.`);
}
}

Usage in a Component:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { UseLoggerService } from './[Link]';

@Component({ /* ... */ })
export class MyComponent implements OnInit, OnDestroy {
constructor(private logger: UseLoggerService) {
// Initialize the custom hook with component-specific data
[Link]('MyComponent');
}

ngOnInit() {
// ... component specific logic
}

ngOnDestroy() {
// The logger service handles its own OnDestroy logic,
// but the component must still implement OnDestroy to ensure Angular calls it.
[Link]();
}
}

b) Explain the role of the event loop and non-blocking I/O in [Link] with examples. [5]

(This is a slightly more detailed combination of Q4 a) ii) and b) from the previous set).
Role of Non-Blocking I/O:
[Link] is designed to handle I/O-intensive tasks (like file system operations, database
queries, and network calls) without freezing the main process thread. It achieves this through
non-blocking I/O.
* When a non-blocking I/O function is called (e.g., [Link]()), [Link] immediately
delegates the task to the operating system or a worker pool.
* The main thread does not wait for the operation to finish; it immediately executes the next
line of code.
Example of Non-Blocking I/O:
[Link]("1. Start reading file...");

// [Link] is non-blocking. It delegates the I/O and immediately returns.


[Link]('/path/to/[Link]', 'utf8', (err, data) => {
// This callback function is placed on the event queue when the file is read.
[Link]("3. File reading finished. Data:", [Link](0, 10));
});

[Link]("2. End of script reached (before file is read).");


// Output order: 1, 2, 3 (illustrating non-blocking behavior)

Role of the Event Loop:


The Event Loop is the heart of [Link] that makes non-blocking I/O possible. It is a
continuous loop that constantly monitors two things:
* The main thread's Call Stack (where synchronous code is executed).
* The Event Queue (where completed I/O callbacks are waiting).
<!-- end list -->
* Mechanism: When the Call Stack is empty (meaning all synchronous code is done), the
Event Loop checks the Event Queue and pushes any waiting callbacks onto the Call Stack
for execution.
* Result: This mechanism ensures that the single main thread is maximally utilized, either
running application logic or preparing the next I/O task, leading to high throughput and
scalability.

c) Describe the role of the OnPush change detection strategy and how it optimizes
performance. [5]

Change Detection (CD) is the mechanism Angular uses to synchronize the application's data
model with the view (DOM). By default, Angular is very aggressive, checking every
component whenever application data might have changed (e.g., after an HTTP request, a
timer event, or a user action).
Role of OnPush Change Detection Strategy:
The OnPush strategy is a performance optimization where a component is configured to run
its change detection only when Angular suspects the inputs it relies on have changed
immutably.
How it Optimizes Performance:
When a component uses OnPush, Angular largely skips checking that component and its
entire subtree of child components during most global change detection cycles. It will only
check the component if one of the following events occurs:
* Input Reference Change: A component's input property (@Input()) changes to a new
object reference (i.e., the reference is immutable). If a property within an object changes but
the object reference remains the same, CD will not be triggered.
* Explicitly Triggered: The component calls [Link]() or
[Link]() manually.
* An Event Fired: An event handler (e.g., a click event) is executed from the component's
own template.
* Async Pipe Emission: An Observable bound to the component's template via the
AsyncPipe emits a new value.
Benefit: By skipping checks on large, static sections of the component tree, OnPush
drastically reduces the total number of checks Angular has to perform, leading to faster
application rendering and a better user experience.

You might also like