0% found this document useful (0 votes)
5 views53 pages

Body Parsing in Express.js Explained

The document explains body parsing in Express.js, detailing how it interprets data in HTTP request bodies using middleware for JSON, URL-encoded, and multipart data. It also covers sending JSON responses with res.json() and the use of status codes. Additionally, it introduces RxJS for reactive programming and NgRx for state management in Angular applications, highlighting their key concepts and advantages.

Uploaded by

akash9561626980
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)
5 views53 pages

Body Parsing in Express.js Explained

The document explains body parsing in Express.js, detailing how it interprets data in HTTP request bodies using middleware for JSON, URL-encoded, and multipart data. It also covers sending JSON responses with res.json() and the use of status codes. Additionally, it introduces RxJS for reactive programming and NgRx for state management in Angular applications, highlighting their key concepts and advantages.

Uploaded by

akash9561626980
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

Learnwithnil

Full Stack development II

Msc computer science sem 3


What is body parsing in [Link]?

In [Link], body parsing refers to the process of interpreting the data sent in the body of
HTTP requests (usually in POST or PUT requests) so that it can be easily accessed and used
within the application. This is crucial because the body of an HTTP request is often used to send
data (like form submissions, JSON, or files) from the client to the server.

By default, Express does not automatically parse the request body. You need to use middleware
to parse the body, depending on the content type of the request (e.g., JSON, URL-encoded, or
multipart).

Types of Body Parsing

Here are some common types of data parsing in [Link]:

1. JSON Parsing: This is used when the request body contains JSON data. Express
provides middleware ([Link]()) to handle this.

Example:

javascript
Copy code
const express = require('express');
const app = express();

[Link]([Link]()); // Body parser for JSON

[Link]('/json', (req, res) => {


[Link]([Link]); // The parsed JSON object
[Link]('JSON data received');
});

[Link](3000);

2. URL-encoded Form Parsing: When the request body contains data sent from an HTML
form with the application/x-www-form-urlencoded content type (common in simple
web forms), Express uses [Link]() middleware to parse it.

Example:
javascript
Copy code
const express = require('express');
const app = express();

[Link]([Link]({ extended: true })); // Body parser for


URL-encoded data

[Link]('/form', (req, res) => {


[Link]([Link]); // The parsed URL-encoded data
[Link]('Form data received');
});

[Link](3000);

3. Multipart/Form-Data Parsing: This type of body parsing is used for file uploads. To
parse multipart/form-data (which is used for file uploads), you typically use an
external library like multer.

Example with Multer (for file uploads):

javascript
Copy code
const express = require('express');
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
const app = express();

[Link]('/upload', [Link]('file'), (req, res) => {


[Link]([Link]); // The uploaded file info
[Link]('File uploaded');
});

[Link](3000);

Why is Body Parsing Needed?

 Access to Data: It helps access the raw data that the client sends in the request body,
such as JSON objects, strings, or files.
 Structured Data: Without body parsing, data would be unreadable or in raw byte form,
making it hard to handle and process.
 Flexibility: Different types of requests (JSON, form data, file uploads) require different
parsing techniques.

In summary, body parsing in [Link] is the middleware mechanism to process the incoming
data in the body of HTTP requests so it can be easily accessed and used in your application.
Express provides built-in middleware for JSON and URL-encoded data, and for more advanced
use cases like file uploads, external libraries like Multer are commonly used.

How do you send a JSON response in [Link]?


In [Link], sending a JSON response is straightforward using the [Link]() method. This
method sends a response with a Content-Type of application/json and serializes the
JavaScript object or value you provide into a JSON string.

Syntax
javascript
Copy code
[Link](data);

 data:The JavaScript object (or any value) that you want to send as a JSON response.
Express automatically converts the object into a JSON string.

Example Usage

Here’s an example of how you can send a JSON response in an Express route:

javascript
Copy code
const express = require('express');
const app = express();

// Example route to send JSON response


[Link]('/data', (req, res) => {
const responseData = {
message: 'Hello, world!',
status: 'success',
timestamp: new Date()
};

[Link](responseData); // Sending JSON response


});

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

Key Points:

1. JSON Response: The [Link]() method automatically sets the Content-Type header
to application/json and converts the object into JSON format.
2. Automatic Serialization: You do not need to manually call [Link](). Express
handles the serialization for you.

Sending a Response with Status Code:


You can also combine [Link]() with a status code. If you want to return a specific HTTP
status code along with the JSON response, you can use [Link]() to set the status code
before calling [Link]():

javascript
Copy code
[Link]('/error', (req, res) => {
const errorResponse = {
error: 'Something went wrong',
status: 'fail'
};

[Link](400).json(errorResponse); // Sends a 400 Bad Request with JSON


});

In this case, the status code 400 is set, and the response body is the JSON object provided.

Response Example

When you visit /data, the response would look like this:

json
Copy code
{
"message": "Hello, world!",
"status": "success",
"timestamp": "2024-12-11T12:00:00.000Z"
}

This is how you send a JSON response from an Express server, making it easy to return
structured data to clients (like web browsers or APIs).

Write a note on RxJS?

RxJS (Reactive Extensions for JavaScript)

RxJS is a library for reactive programming using Observables, which allows developers to work
with asynchronous data streams more efficiently. It provides a powerful and flexible way to
manage asynchronous events and data flows, making it particularly useful for scenarios like
handling user input, HTTP requests, WebSocket communication, or any event-driven
architecture.

Key Concepts of RxJS


1. Observables: An Observable represents a stream of data that can be observed. It can
emit zero or more values over time, either synchronously or asynchronously. Observables
are the foundation of RxJS.

javascript
Copy code
import { Observable } from 'rxjs';

const observable = new Observable(subscriber => {


[Link]('Hello');
[Link]('RxJS');
[Link]();
});

2. Observers: An Observer subscribes to an Observable to receive the data that it emits.


The Observer defines the actions to take when receiving data (next), when an error
occurs (error), or when the Observable completes (complete).

javascript
Copy code
const observer = {
next: value => [Link]('Received:', value),
error: err => [Link]('Error:', err),
complete: () => [Link]('Completed!')
};

[Link](observer);

3. Operators: RxJS provides a rich set of operators to transform, filter, combine, and
manipulate streams of data. These operators are used to manage the flow of data and add
reactive behavior.
o Map: Transforms the data.
o Filter: Filters the stream of data based on a condition.
o MergeMap: Flattens multiple Observables into one.
o ConcatMap: Similar to mergeMap, but processes Observables in sequence.

Example using map operator:

javascript
Copy code
import { map } from 'rxjs';

const observable = new Observable(subscriber => {


[Link](1);
[Link](2);
[Link]();
});

[Link](
map(x => x * 2) // Multiply each value by 2
).subscribe([Link]);
4. Subjects: A Subject is a special type of Observable that allows you to multicast values to
many Observers. It acts as both an Observer and an Observable, meaning you can both
subscribe to it and emit values into it.

javascript
Copy code
import { Subject } from 'rxjs';

const subject = new Subject();

[Link](value => [Link]('Observer 1:', value));


[Link](value => [Link]('Observer 2:', value));

[Link]('Hello'); // Both observers will receive this value

5. Schedulers: Schedulers control the timing of the emissions from an Observable. They
allow you to control when and how the values are emitted, making it possible to schedule
tasks and manage concurrency in reactive streams.

Advantages of RxJS

1. Asynchronous Programming Made Simple: RxJS abstracts away complex async logic
such as callbacks, promises, and event handlers into an elegant and declarative approach,
allowing developers to manage async streams more naturally.
2. Composability: Operators allow you to compose complex asynchronous flows and
transformations in a clean and readable manner. You can chain operators to handle
events, transform data, and handle errors without deeply nested callbacks.
3. Declarative Code: RxJS promotes a declarative style of programming where you
describe the sequence of operations (such as mapping, filtering, merging, etc.) rather than
manually managing the flow of events.
4. Efficient Memory Management: RxJS provides mechanisms like unsubscribe() that
allow you to handle resources more efficiently, avoiding memory leaks. Operators like
takeUntil and takeWhile help with automatically managing subscriptions.
5. Stream Handling: RxJS makes it easy to handle streams of data such as user inputs,
WebSocket messages, or even events from multiple sources, all in one unified manner.

Use Cases of RxJS

1. Handling User Input: RxJS is excellent for managing complex user interactions like
form inputs, mouse events, key presses, and more. For instance, you can debounce user
input, filter values, and react to events in a cleaner way than with traditional methods.
2. HTTP Requests: RxJS can be used with HTTP requests, where the response is an
Observable, allowing chaining of operators to handle request flow, retries, and errors.

Example with fetch and RxJS:

javascript
Copy code
import { fromFetch } from 'rxjs';

const data$ = fromFetch('[Link]

data$.subscribe({
next: response => [Link](response),
error: err => [Link]('Request failed', err),
complete: () => [Link]('Request complete')
});

3. Real-Time Applications: In applications like chat apps or live data streams, RxJS can
simplify the management of real-time data streams, like WebSocket or Server-Sent
Events (SSE).
4. Event-driven Programming: For event-based architectures or applications, RxJS makes
it easy to manage multiple events, their transformations, and actions in response to those
events.

Conclusion

RxJS is a powerful library that offers a reactive, declarative approach to handling asynchronous
data streams. By using Observables and operators, developers can create complex and efficient
reactive applications while keeping the code clean and maintainable. Its usage has become
especially popular in modern frameworks like Angular, where it is often used to manage HTTP
requests, forms, and other event-driven programming tasks.

Explain State management with NgRx?


State Management with NgRx

NgRx is a popular library for managing state in Angular applications. It is inspired by the Redux
pattern from the React ecosystem but is specifically built for Angular. NgRx uses a reactive
approach to manage the application's state by leveraging RxJS Observables. It provides a way to
handle application state in a predictable, centralized manner, making it easier to track changes
and debug applications.

In essence, NgRx follows the Redux principles but integrates well with Angular’s component-
driven architecture and the reactive programming model.

Key Concepts of NgRx

1. Store: The store in NgRx is the central entity where the application's state is held. The
store provides a single source of truth for the entire application state. Instead of each
component managing its own state, components in an NgRx-powered application
communicate with the store to access and update the state.
2. Actions: Actions are events or commands that describe something that has happened in
the application. Actions are dispatched to trigger state changes. They are the only way to
interact with the store.
o Actions are plain objects with at least a type property that describes the action.
o Actions can also carry payloads of additional data that are needed for processing.

Example:

typescript
Copy code
export const loadData = createAction('[Data] Load Data');
export const loadDataSuccess = createAction('[Data] Load Data Success',
props<{ data: any[] }>());
export const loadDataFailure = createAction('[Data] Load Data Failure',
props<{ error: any }>());

3. Reducers: A reducer is a function that takes the current state and an action as inputs,
and returns a new state based on the action's type and payload. Reducers are pure
functions, meaning they should not mutate the state directly but instead return a new state
object.

Example:

typescript
Copy code
export const dataReducer = createReducer(
initialState,
on(loadData, state => ({ ...state, loading: true })),
on(loadDataSuccess, (state, { data }) => ({ ...state, loading: false,
data })),
on(loadDataFailure, (state, { error }) => ({ ...state, loading:
false, error }))
);

4. Selectors: Selectors are functions that allow you to select or retrieve specific parts of the
store’s state. They can be used to compute derived state or access nested data. Selectors
are often memoized, meaning they will return the cached result unless the selected state
changes, improving performance.

Example:

typescript
Copy code
export const selectData = createSelector(
selectFeatureState,
(state: State) => [Link]
);
5. Effects: Effects handle side effects like asynchronous operations (e.g., HTTP requests),
external interactions, and logging. They listen for specific actions and can dispatch new
actions in response, typically after completing asynchronous operations.

Example:

typescript
Copy code
@Injectable()
export class DataEffects {
loadData$ = createEffect(() =>
[Link]$.pipe(
ofType(loadData),
switchMap(() =>
[Link]().pipe(
map(data => loadDataSuccess({ data })),
catchError(error => of(loadDataFailure({ error })))
)
)
)
);

constructor(private actions$: Actions, private dataService:


DataService) {}
}

6. State Management Flow: The typical flow of state management in NgRx can be
outlined as:
1. Action is Dispatched: A component or service dispatches an action (e.g.,
loadData).
2. Reducer Processes Action: The reducer receives the action and updates the state
based on the action's type.
3. State is Updated: The store is updated with the new state.
4. Effects Handle Side Effects: If the action triggers an asynchronous operation
(e.g., fetching data), an effect will listen to the action and perform the necessary
side effects, dispatching success or failure actions.
5. Selectors Retrieve State: Components or services select the state using selectors
to display or interact with the updated state.

Example of a Full NgRx Flow

1. Action: We define an action to load data:

typescript
Copy code
export const loadData = createAction('[Data] Load Data');
export const loadDataSuccess = createAction('[Data] Load Data Success',
props<{ data: any[] }>());
export const loadDataFailure = createAction('[Data] Load Data Failure',
props<{ error: any }>());
2. Reducer: A reducer handles these actions and updates the store:

typescript
Copy code
export const initialState: State = {
loading: false,
data: [],
error: null
};

export const dataReducer = createReducer(


initialState,
on(loadData, state => ({ ...state, loading: true })),
on(loadDataSuccess, (state, { data }) => ({ ...state, loading: false,
data })),
on(loadDataFailure, (state, { error }) => ({ ...state, loading:
false, error }))
);

3. Effect: An effect listens for the loadData action and fetches data from a service:

typescript
Copy code
@Injectable()
export class DataEffects {
loadData$ = createEffect(() =>
[Link]$.pipe(
ofType(loadData),
switchMap(() =>
[Link]().pipe(
map(data => loadDataSuccess({ data })),
catchError(error => of(loadDataFailure({ error })))
)
)
)
);

constructor(private actions$: Actions, private dataService:


DataService) {}
}

4. Component: A component dispatches the action and selects the data from the store:

typescript
Copy code
@Component({
selector: 'app-data',
templateUrl: './[Link]'
})
export class DataComponent implements OnInit {
data$ = [Link](selectData);
loading$ = [Link](selectLoading);

constructor(private store: Store) {}


ngOnInit() {
[Link](loadData());
}
}

Benefits of Using NgRx

1. Centralized State: All application state is managed in a single store, making it easier to
track and debug.
2. Predictable State: State transitions are handled in a predictable way using actions and
reducers, reducing complexity and improving maintainability.
3. Separation of Concerns: NgRx promotes a clear separation of concerns between
components, state management, and side effects (via effects).
4. Asynchronous Handling: Effects provide a clean way to manage side effects such as
HTTP requests and other asynchronous operations.
5. Testability: The use of pure functions for reducers and actions makes it easier to write
unit tests for the application state and logic.

Conclusion

NgRx is a powerful and scalable solution for managing state in Angular applications, especially
for larger and more complex apps with significant asynchronous interactions. By using the
Redux pattern combined with Angular’s reactive programming paradigm, NgRx helps
developers build maintainable, predictable, and testable applications. It may introduce a learning
curve, but once understood, it provides a robust framework for handling state in Angular
applications efficiently.

5. Define Lazy Loading in Angular

Lazy loading in Angular is a design pattern used to load modules only when they are needed,
rather than loading them upfront with the initial application load. This improves performance,
especially in large applications, by reducing the initial load time and only loading the necessary
parts of the app when the user navigates to a specific route. Lazy loading is typically
implemented using the Angular Router and can be configured using the loadChildren property
in routing.

Example:

typescript
Copy code
const routes: Routes = [
{
path: 'feature',
loadChildren: () => import('./feature/[Link]').then(m =>
[Link])
}
];

6. What is the Role of Dependency Injection in Angular?

Dependency Injection (DI) is a design pattern and core concept in Angular. It allows objects to
be injected into a class, rather than the class creating them itself. In Angular, DI is used to
provide services and other dependencies to components, directives, pipes, and other services. It
improves modularity, testability, and flexibility by decoupling the components from their
dependencies. The Angular framework handles the lifecycle and instantiation of dependencies
automatically.

Example:

typescript
Copy code
@Injectable({
providedIn: 'root'
})
export class MyService {
constructor(private http: HttpClient) { }
}

7. How Does TypeScript Enforce Type Safety in Angular Applications?

TypeScript enforces type safety in Angular applications by providing a static type system. This
allows developers to define the types of variables, function parameters, return values, and
properties, ensuring that data conforms to expected types at compile time. TypeScript helps catch
errors early, improving the maintainability and reliability of code. For example, it prevents
passing a string where a number is expected, or calling a method on an object that does not have
that method.

Example:

typescript
Copy code
let age: number = 30; // TypeScript enforces that 'age' must be a number
age = '30'; // This will cause an error because 'age' is declared as a number

8. What is NgRx?

NgRx is a state management library for Angular applications, inspired by Redux. It uses
Observables to manage state reactively, making it easier to handle complex application states.
NgRx is built around the Store pattern, where the state of the application is centralized in one
place, and changes are managed through actions and reducers. It also supports effects to
manage side effects like HTTP requests. NgRx improves the predictability, maintainability, and
testability of Angular apps.
9. Define a Subject in RxJS

A Subject in RxJS is a special type of Observable that allows values to be multicasted to many
Observers. Unlike a regular Observable, which only sends notifications to subscribers, a Subject
can act as both an Observable and an Observer. This means it can both emit values and listen to
them. Subjects are often used to share values among multiple parts of an application.

Example:

typescript
Copy code
import { Subject } from 'rxjs';

const subject = new Subject();

[Link](value => [Link](`Observer 1: ${value}`));


[Link](value => [Link](`Observer 2: ${value}`));

[Link]('Hello'); // Both observers receive 'Hello'

10. What is an Observable in RxJS?

An Observable in RxJS is a data stream that can emit values over time. It allows you to model
asynchronous operations like HTTP requests, user inputs, and WebSocket messages.
Observables are the core concept of reactive programming and are used to represent events, data,
or messages. You can subscribe to an Observable to start receiving its values, and you can use
operators to transform, filter, and combine these streams.

Example:

typescript
Copy code
import { Observable } from 'rxjs';

const observable = new Observable(subscriber => {


[Link]('First value');
[Link]('Second value');
[Link]();
});

[Link]({
next: value => [Link](value),
complete: () => [Link]('Done!')
});

11. What are the Testing Strategies used for AngularJS Applications?

In AngularJS (the earlier version of Angular), common testing strategies included:


 Unit Testing: Testing individual components, services, and directives to ensure they
work as expected in isolation. Tools like Jasmine and Karma were commonly used.
 Integration Testing: Testing how different parts of the application work together. This
involved testing components with their dependencies.
 End-to-End (E2E) Testing: Testing the full application flow, simulating user
interactions. Tools like Protractor were used for E2E tests.

12. What are the Testing Strategies used for Angular Applications?

In Angular (the modern version), testing strategies are similar to AngularJS but with some
improvements:

 Unit Testing: Using Jasmine for writing tests and Karma for running them, unit tests
are written for services, components, pipes, and directives.
 Component Testing: Angular provides TestBed to configure and test Angular
components in isolation, allowing you to mock dependencies and simulate user
interaction.
 End-to-End (E2E) Testing: Tools like Cypress or Protractor are used to simulate real
user scenarios and test the whole application. Cypress is gaining popularity due to its
speed and ease of use.

13. Write a Note on Core Concepts of RxJS

The core concepts of RxJS revolve around Observables, Observers, and Operators:

1. Observables: Represent streams of data that can emit values over time. They can handle
both synchronous and asynchronous data.
2. Observers: Functions that subscribe to an Observable and define how to react to the data
emitted by the Observable.
3. Operators: Functions that allow you to transform, filter, combine, and manipulate data
streams. Some common operators include:
o map(): Transforms emitted values.
o filter(): Filters emitted values based on a condition.
o mergeMap(), concatMap(): Handle multiple Observables.
o catchError(): Handles errors in a stream.
4. Subjects: Special types of Observables that allow values to be multicasted to multiple
subscribers. Subjects are useful for sharing data and acting as a bridge between different
parts of an application.
5. Schedulers: Manage the execution of Observables, allowing you to control when and
how values are emitted.

RxJS is widely used in Angular to handle asynchronous data, such as HTTP requests, events, and
user input, and it provides a declarative way to manage complex data flows.
1. What is the purpose of @Input() and @Output() in Angular?

 @Input(): The @Input() decorator is used to pass data from a parent component to a
child component. It allows the child component to receive data from the parent and use it
within the component. Essentially, @Input() marks a property of a child component as a
target for data binding from the parent component.

Example:

typescript
Copy code
@Component({
selector: 'app-child',
template: `<p>{{message}}</p>`
})
export class ChildComponent {
@Input() message: string;
}

In the parent component:

html
Copy code
<app-child [message]="parentMessage"></app-child>

 @Output(): The @Output() decorator is used to send data from a child component to a
parent component. It is commonly used with an EventEmitter to emit events that the
parent component can listen to. This creates a mechanism for child components to
communicate back to their parents.

Example:

typescript
Copy code
@Component({
selector: 'app-child',
template: `<button (click)="sendData()">Send</button>`
})
export class ChildComponent {
@Output() dataEvent = new EventEmitter<string>();

sendData() {
[Link]('Data from child');
}
}

In the parent component:


html
Copy code
<app-child (dataEvent)="receiveData($event)"></app-child>

2. Explain the concept of custom life-cycle hooks in Angular.

Angular provides a set of predefined lifecycle hooks that allow developers to tap into the
different stages of a component’s life, such as creation, updates, and destruction. However,
Angular doesn’t allow custom lifecycle hooks directly. Developers can use predefined lifecycle
hooks like ngOnInit, ngOnChanges, and others to customize the behavior during specific stages.
For example, custom logic like fetching data from an API or performing clean-up tasks can be
written in these hooks.

However, there is no concept of truly "custom" lifecycle hooks beyond the predefined ones
provided by Angular. These hooks are sufficient for managing and responding to various events
in a component’s lifecycle.

3. Describe how the OnPush change detection strategy works and how it
optimizes performance.

In Angular, the default change detection strategy checks all components in the component tree
for changes whenever any change occurs. This can be inefficient in larger applications.

The OnPush change detection strategy optimizes performance by reducing the number of checks
Angular performs. When a component uses the OnPush strategy, Angular only checks the
component and its children for changes under the following conditions:

 Input properties change (when an @Input() bound value changes).


 An event is triggered (like a click event).
 A component explicitly calls markForCheck().

This means that Angular does not check the component for changes every time the application
state changes, but rather only when something the component depends on actually changes.

Example:

typescript
Copy code
@Component({
selector: 'app-example',
changeDetection: [Link],
template: `<p>{{data}}</p>`
})
export class ExampleComponent {
@Input() data: string;
}
By using OnPush, Angular checks only when necessary, significantly improving performance,
especially in large applications.

4. Explain the purpose of the following Angular lifecycle hooks:

 ngOnChanges():
o This hook is called whenever an @Input() property of the component changes.
It’s called before ngOnInit and can be used to react to changes in the input
values. It receives a SimpleChanges object, which contains the previous and
current values of the inputs.

Example:

typescript
Copy code
ngOnChanges(changes: SimpleChanges) {
[Link]('Previous:', changes['inputData'].previousValue);
[Link]('Current:', changes['inputData'].currentValue);
}

 ngOnInit():
o This hook is called once after the component’s first change detection cycle, i.e.,
after the component's input properties are initialized. It’s commonly used for
initialization tasks like fetching data from a server.

Example:

typescript
Copy code
ngOnInit() {
[Link]();
}

 ngDoCheck():
o This hook is called during every change detection cycle, regardless of whether the
input properties have changed. It’s useful for custom change detection or when
you need to perform tasks not automatically handled by Angular’s default change
detection.

Example:

typescript
Copy code
ngDoCheck() {
[Link]('Change detection cycle has run.');
}

 ngAfterContentInit():
o This hook is called once after Angular has projected content into the component,
meaning it is called after content (from <ng-content>) is placed inside the
component’s view. This is useful if you need to perform actions once the content
is ready.

Example:

typescript
Copy code
ngAfterContentInit() {
[Link]('Content has been projected into the component.');
}

5. Explain the need for security in Angular and XSS, CSRF prevention

Security is crucial in Angular applications to prevent vulnerabilities that can be exploited by


attackers. Angular has several built-in features to mitigate common security issues like Cross-
Site Scripting (XSS) and Cross-Site Request Forgery (CSRF).

 XSS (Cross-Site Scripting): XSS occurs when attackers inject malicious scripts into web
pages that are viewed by other users. This can lead to stealing sensitive data, session
hijacking, etc. Angular prevents XSS by automatically escaping HTML, CSS, and
JavaScript in the templates to ensure that any injected content is treated as plain text, not
executable code.

Example: Angular automatically escapes dangerous characters like <, >, and & in the
template, so even if malicious data is rendered, it won’t be executed as code.

html
Copy code
<div>{{userInput}}</div> <!-- Automatically escapes dangerous HTML
content -->

 CSRF (Cross-Site Request Forgery): CSRF occurs when an attacker tricks the user into
making unwanted requests to a server that the user is authenticated on. This is commonly
done by sending requests with the user's credentials (like cookies or tokens) to perform
actions on behalf of the user without their consent.

To prevent CSRF attacks, Angular provides an HttpClient that can be configured to send
a CSRF token with requests. The server needs to validate this token to ensure that the
request is legitimate.

Example:

typescript
Copy code
@Injectable({
providedIn: 'root'
})
export class AuthService {
constructor(private http: HttpClient) {}

login(credentials: any) {
return [Link]('/api/login', credentials, {
headers: new HttpHeaders().set('X-CSRF-Token',
[Link]())
});
}

private getCsrfToken() {
return [Link]('=')[1]; // Example for extracting
CSRF token from cookies
}
}

By implementing these security measures and practices, Angular helps developers protect their
applications from common web vulnerabilities.

Unit - 2 Mastering Type Script

1-2 Marks Question 1. What is a decorator in TypeScript? 2. What are utility types in TypeScript? 4-5
Marks Question 1. Explain method decorator in TypeScript. 2. Demonstrate generics in TypeScript with
suitable example. 3. What are utility types in TypeScript?Explain Conditional Type (any four)? 4. What
are decorators in TypeScript? Provide an example of using a class decorator. 5. What are decorators in
TypeScript? Provide an example of using a class decorator. 6. What are utility types in TypeScript.
Explain Conditional Type (any four)?

1. What is a Decorator in TypeScript?

A decorator in TypeScript is a special kind of function that can be applied to classes, methods,
properties, or parameters to modify their behavior or add additional functionality. Decorators are
part of the metadata reflection mechanism in TypeScript, which allows you to add metadata or
modify the way elements work at runtime.

Decorators are prefixed with an @ symbol and are often used in frameworks like Angular to add
behaviors to classes, properties, and methods.
There are several types of decorators in TypeScript:

 Class decorators: Applied to a class definition.


 Method decorators: Applied to methods of a class.
 Property decorators: Applied to properties of a class.
 Parameter decorators: Applied to parameters of a class method.

Example of a Class Decorator:


typescript
Copy code
function Component(target: Function) {
[Link](`Component created: ${[Link]}`);
}

@Component
class MyComponent {
constructor() {
[Link]('MyComponent initialized');
}
}

In this example:

 The @Component decorator is applied to the MyComponent class.


 When MyComponent is defined, the decorator is executed and logs a message.

Example of a Method Decorator:


typescript
Copy code
function Log(target: any, key: string, descriptor: PropertyDescriptor) {
const originalMethod = [Link];
[Link] = function (...args: any[]) {
[Link](`Method ${key} called with arguments:`, args);
return [Link](this, args);
};
}

class MyClass {
@Log
myMethod(arg: number) {
[Link]('Method executed with arg:', arg);
}
}

const obj = new MyClass();


[Link](5);

In this example, the @Log decorator is applied to the myMethod method to log the arguments
when the method is called.
Types of Decorators:

 Class decorators: Used to modify or enhance a class.


 Method decorators: Used to modify or enhance methods.
 Property decorators: Used to modify or enhance properties.
 Parameter decorators: Used to modify or enhance parameters.

Decorators are an experimental feature in TypeScript and require enabling the


experimentalDecorators option in the [Link] file.

json
Copy code
{
"compilerOptions": {
"experimentalDecorators": true
}
}

2. What are Utility Types in TypeScript?

Utility types in TypeScript are predefined generic types that help perform common
transformations or operations on types. These utility types simplify type manipulation, making
code more concise and readable. They can be used to create new types based on existing ones.

Some of the most commonly used utility types in TypeScript include:

1. Partial<T>

The Partial<T> utility type makes all properties of a given type T optional.

typescript
Copy code
interface Person {
name: string;
age: number;
}

const person: Partial<Person> = { name: 'John' }; // Only the name property


is required, age is optional

2. Required<T>

The Required<T> utility type makes all properties of a given type T required, even if they were
originally optional.

typescript
Copy code
interface Person {
name: string;
age?: number;
}

const person: Required<Person> = { name: 'John', age: 30 }; // Now 'age' is


required

3. Readonly<T>

The Readonly<T> utility type makes all properties of a given type T read-only, meaning they
cannot be reassigned after initialization.

typescript
Copy code
interface Person {
name: string;
age: number;
}

const person: Readonly<Person> = { name: 'John', age: 30 };


[Link] = 31; // Error: Cannot assign to 'age' because it is a read-only
property

4. Pick<T, K>

The Pick<T, K> utility type allows you to create a new type by picking a subset of properties K
from the type T.

typescript
Copy code
interface Person {
name: string;
age: number;
address: string;
}

type PersonNameAndAge = Pick<Person, 'name' | 'age'>; // Creates a new type


with only 'name' and 'age'

5. Omit<T, K>

The Omit<T, K> utility type creates a new type by omitting certain properties K from the type T.

typescript
Copy code
interface Person {
name: string;
age: number;
address: string;
}

type PersonWithoutAddress = Omit<Person, 'address'>; // Creates a new type


without the 'address' property
6. Record<K, T>

The Record<K, T> utility type constructs a type with a set of properties K of type T. This is
useful for creating objects with specific keys and values.

typescript
Copy code
type Person = Record<'name' | 'age', string>;

const person: Person = {


name: 'John',
age: '30'
};

7. Exclude<T, U>

The Exclude<T, U> utility type constructs a type by excluding types from T that are assignable
to U.

typescript
Copy code
type A = string | number | boolean;
type B = Exclude<A, boolean>; // Excludes 'boolean' from 'A', resulting in
'string | number'

8. Extract<T, U>

The Extract<T, U> utility type constructs a type by extracting the types from T that are
assignable to U.

typescript
Copy code
type A = string | number | boolean;
type B = Extract<A, string | number>; // Extracts 'string | number' from 'A'

9. NonNullable<T>

The NonNullable<T> utility type constructs a type by removing null and undefined from the
type T.

typescript
Copy code
type A = string | number | null | undefined;
type B = NonNullable<A>; // Removes 'null' and 'undefined' from 'A',
resulting in 'string | number'

10. Infer

The infer keyword is used in conditional types to infer a type within a conditional block. It’s
often used to extract a type from another type.
typescript
Copy code
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

Summary of Utility Types:

 Partial<T>: Makes all properties optional.


 Required<T>: Makes all properties required.
 Readonly<T>: Makes all properties read-only.
 Pick<T, K>: Selects a subset of properties from T.
 Omit<T, K>: Removes certain properties from T.
 Record<K, T>: Creates an object type with specific keys and values.
 Exclude<T, U>: Excludes types from T that are assignable to U.
 Extract<T, U>: Extracts types from T that are assignable to U.
 NonNullable<T>: Removes null and undefined from a type.
 Infer: Extracts types from a conditional type.

Utility types allow developers to manipulate types in a flexible and reusable way, making
TypeScript a more powerful language for handling complex type transformations.

1. Explain Method Decorator in TypeScript

A method decorator in TypeScript is a function that is applied to a method in a class. It allows


us to modify or extend the behavior of methods. Method decorators are defined using the @
symbol followed by a function. The decorator is applied to the method, and it can access
metadata about the method, such as the target object, the method's name, and the method's
descriptor (which defines how the method is invoked).

A method decorator function takes three parameters:

 target: The prototype of the class.


 propertyKey: The name of the method.
 descriptor: A property descriptor that allows manipulation of the method (e.g., to change its
behavior).

Example of Method Decorator:


typescript
Copy code
function Log(target: any, propertyKey: string, descriptor:
PropertyDescriptor) {
const originalMethod = [Link];
[Link] = function (...args: any[]) {
[Link](`Method ${propertyKey} was called with arguments: ${args}`);
const result = [Link](this, args);
[Link](`Method ${propertyKey} returned: ${result}`);
return result;
};
}

class Calculator {
@Log
add(a: number, b: number) {
return a + b;
}
}

const calc = new Calculator();


[Link](2, 3); // Logs method call details

In this example:

 The Log decorator wraps the add method, logging the arguments and the result when the
method is called.

2. Demonstrate Generics in TypeScript with Suitable Example

Generics in TypeScript allow you to define reusable components or functions while maintaining
type safety. They enable you to work with different data types without compromising on the
specific type checks.

Example of Generics in a Function:


typescript
Copy code
function identity<T>(arg: T): T {
return arg;
}

let output1 = identity<string>('Hello, TypeScript');


let output2 = identity<number>(123);

[Link](output1); // Output: Hello, TypeScript


[Link](output2); // Output: 123

In this example:

 The identity function is a generic function that accepts a parameter of type T and returns a
value of type T.
 The type T is inferred from the passed argument, ensuring that the function is type-safe.

Example of Generics with Classes:


typescript
Copy code
class Box<T> {
private value: T;

constructor(value: T) {
[Link] = value;
}

getValue(): T {
return [Link];
}
}

let stringBox = new Box<string>('Hello');


let numberBox = new Box<number>(42);

[Link]([Link]()); // Output: Hello


[Link]([Link]()); // Output: 42

In this example:

 The Box class uses a generic type T to hold a value, and the type of the value is determined
when the class is instantiated.

3. What are Utility Types in TypeScript? Explain Conditional Type (Any Four)?

Utility types in TypeScript are pre-defined generic types that allow you to perform type
transformations and operations. These utility types can help manipulate existing types in a
concise and reusable manner.

Some commonly used utility types are:

1. Partial<T>:

The Partial<T> utility type makes all properties of a given type T optional.

typescript
Copy code
interface Person {
name: string;
age: number;
}

const person: Partial<Person> = { name: 'John' }; // Only the name property


is required

2. Required<T>:

The Required<T> utility type makes all properties of a given type T required.

typescript
Copy code
interface Person {
name: string;
age?: number;
}

const person: Required<Person> = { name: 'John', age: 30 }; // Both


properties are required

3. Readonly<T>:

The Readonly<T> utility type makes all properties of a given type T read-only, meaning they
cannot be reassigned after initialization.

typescript
Copy code
interface Person {
name: string;
age: number;
}

const person: Readonly<Person> = { name: 'John', age: 30 };


[Link] = 31; // Error: Cannot assign to 'age' because it is a read-only
property

4. Record<K, T>:

The Record<K, T> utility type constructs an object type with keys of type K and values of type
T.

typescript
Copy code
type RolePermissions = Record<string, boolean>;

const permissions: RolePermissions = {


admin: true,
user: false
};

4. What are Decorators in TypeScript? Provide an Example of Using a Class


Decorator.

Decorators in TypeScript are functions that can be applied to classes, methods, properties, or
parameters to modify or extend their behavior. A class decorator is a special kind of decorator
applied to a class constructor to modify its behavior.

Example of Class Decorator:


typescript
Copy code
function ClassLogger(target: Function) {
[Link](`Class ${[Link]} was created.`);
}

@ClassLogger
class MyClass {
constructor() {
[Link]('MyClass instance created.');
}
}

const myClassInstance = new MyClass();


// Output:
// Class MyClass was created.
// MyClass instance created.

In this example:

 The @ClassLogger decorator is applied to MyClass. It logs a message when the class is
created.

5. What are Decorators in TypeScript? Provide an Example of Using a Class


Decorator.

This question is similar to the previous one, so the answer is already covered above. However, I
will provide another example of a class decorator for clarity.

Another Example of Class Decorator:


typescript
Copy code
function Timestamp(target: Function) {
[Link] = new Date();
}

@Timestamp
class Event {
constructor(public name: string) {}
}

const event = new Event('Birthday Party');


[Link]([Link]); // Output: Current date and time

In this example:

 The Timestamp decorator adds a timestamp property to the class, holding the current date
and time when an instance is created.

6. What are Utility Types in TypeScript? Explain Conditional Type (Any Four)?

As mentioned earlier, utility types are predefined types in TypeScript that help manipulate and
transform types. In addition to the commonly used utility types already discussed, conditional
types are a powerful feature in TypeScript that allow you to create types based on conditions.
1. Conditional Types:

Conditional types allow you to create types based on a condition, typically checking if one type
extends another type.

typescript
Copy code
type IsString<T> = T extends string ? 'Yes' : 'No';

type A = IsString<string>; // 'Yes'


type B = IsString<number>; // 'No'

2. Extract<T, U>:

The Extract<T, U> utility type extracts types from T that are assignable to U.

typescript
Copy code
type A = string | number | boolean;
type B = Extract<A, string | number>; // 'string | number'

3. Exclude<T, U>:

The Exclude<T, U> utility type removes types from T that are assignable to U.

typescript
Copy code
type A = string | number | boolean;
type B = Exclude<A, boolean>; // 'string | number'

4. NonNullable<T>:

The NonNullable<T> utility type removes null and undefined from T.

typescript
Copy code
type A = string | number | null | undefined;
type B = NonNullable<A>; // 'string | number'

Summary:

 Method Decorators modify the behavior of methods.


 Generics allow reusable functions and classes with flexible types.
 Utility Types like Partial, Required, Readonly, and Record provide commonly used
transformations.
 Decorators are functions that modify classes, methods, or properties in TypeScript.
 Conditional Types allow dynamic type creation based on conditions.
1. What is body parsing in [Link]?
2. 2. How do you send a JSON response in [Link]?
3. 3. Which middleware is used in [Link] to parse JSON request bodies?
4. 4. Define lazy loading in Angular.
5. 5. What is the role of dependency injection in Angular?
6. 6. How does TypeScript enforce type safety in Angular applications?
7. 7. What is body parsing in [Link]? 8. Explain the concept of middleware in [Link].

1. What is body parsing in [Link]?

Body parsing in [Link] refers to the process of extracting and parsing the body of incoming
HTTP requests. When a client sends data to the server (e.g., through a POST request), the data is
typically included in the request body. [Link], by default, does not parse the body of requests.
Instead, middleware is used to parse the body content and make it available in the request object
([Link]).

For example, in a JSON payload, body parsing ensures that the data is parsed and converted into
a JavaScript object, making it easy to interact with the data.

2. How do you send a JSON response in [Link]?

In [Link], to send a JSON response, you can use the [Link]() method. This method sends
a JSON-formatted response to the client. It automatically sets the Content-Type header to
application/json and converts the JavaScript object or array into a JSON string.

Example:
javascript
Copy code
[Link]('/data', (req, res) => {
const data = { message: 'Hello, World!' };
[Link](data);
});

In this example, the [Link]() method sends a JSON response containing { message:
'Hello, World!' }.

3. Which middleware is used in [Link] to parse JSON request bodies?

In [Link], the middleware used to parse JSON request bodies is [Link](). This
middleware is built into Express and is used to automatically parse incoming JSON data in the
request body, making it available as [Link].
Example:
javascript
Copy code
const express = require('express');
const app = express();

// Middleware to parse JSON


[Link]([Link]());

[Link]('/submit', (req, res) => {


[Link]([Link]); // The parsed JSON body
[Link]('Data received');
});

Here, the [Link]() middleware parses the incoming request body, and the data is
accessible via [Link].

4. Define lazy loading in Angular.

Lazy loading in Angular is a technique used to load feature modules only when they are needed,
instead of loading all modules at the start of the application. This improves the performance of
the application by reducing the initial load time and only loading the necessary resources when
the user navigates to specific parts of the app.

In Angular, lazy loading is achieved using the loadChildren property in the router
configuration. Instead of importing the module directly, Angular loads the module only when the
route corresponding to that module is accessed.

Example of lazy loading in Angular:


typescript
Copy code
const routes: Routes = [
{ path: 'feature', loadChildren: () =>
import('./feature/[Link]').then(m => [Link]) }
];

In this example, the FeatureModule is lazy-loaded when the user navigates to the /feature
route.

5. What is the role of dependency injection in Angular?

Dependency Injection (DI) is a design pattern used in Angular to manage the dependencies of a
class or service. DI allows objects to be provided with their dependencies rather than creating
them internally. In Angular, services, components, and other classes can have their dependencies
injected automatically by the Angular injector.

The main benefits of DI in Angular are:


 Decoupling components: Components and services do not need to know about how their
dependencies are created.
 Reusability: Dependencies can be shared across multiple components or services.
 Testability: DI makes it easier to mock services for unit testing.

Example:
typescript
Copy code
@Injectable({
providedIn: 'root'
})
export class MyService {
constructor(private http: HttpClient) {}
}

Here, HttpClient is injected into the MyService class.

6. How does TypeScript enforce type safety in Angular applications?

TypeScript enforces type safety in Angular applications by using static typing. This means that
developers define types for variables, function parameters, and return values at compile time.
TypeScript then checks that the values conform to these types during development and alerts
developers to potential errors before runtime.

For example:

 Type annotations: Developers explicitly define types for variables, function parameters, and
return types.
 Interface & Class types: TypeScript can enforce the structure of objects using interfaces or class
types.
 Generics: TypeScript allows defining generic types for reusable components or functions,
ensuring type safety across different types.

Example:
typescript
Copy code
function greet(name: string): string {
return `Hello, ${name}`;
}

greet(123); // Error: Argument of type 'number' is not assignable to


parameter of type 'string'.

In this example, TypeScript enforces that the argument passed to the greet function must be of
type string.

7. What is body parsing in [Link]?


This question is a duplicate of Question 1. As previously explained, body parsing in [Link]
refers to the process of parsing the body of incoming HTTP requests to make the data accessible
in [Link].

8. Explain the concept of middleware in [Link].

In [Link], middleware is a function that sits between the request and response cycle. It
processes requests and modifies them (if necessary), executes code, handles errors, or terminates
the request-response cycle. Middleware functions can be used for tasks like logging,
authentication, parsing request bodies, serving static files, and error handling.

Middleware functions can be applied globally or to specific routes. Express provides a simple
API to create and manage middleware functions.

Types of Middleware:

 Application-level middleware: Bound to the app and is executed on all routes.


 Router-level middleware: Bound to specific routers.
 Error-handling middleware: Used to handle errors in the application.

Example of middleware:
javascript
Copy code
const express = require('express');
const app = express();

// Simple logging middleware


[Link]((req, res, next) => {
[Link](`Request received at ${[Link]}`);
next(); // Pass the request to the next middleware or route handler
});

// A route
[Link]('/', (req, res) => {
[Link]('Hello, World!');
});

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

In this example:

 The [Link] function registers a middleware that logs each request.


 next() is called to pass the control to the next middleware or route handler.

Summary of Key Points:

 Body parsing in [Link] is done with middleware like [Link]().


 To send a JSON response in [Link], use [Link]().
 Lazy loading in Angular improves performance by loading modules on demand.
 Dependency Injection in Angular manages services and objects, making the app more
maintainable and testable.
 TypeScript enforces type safety in Angular by using static typing and compile-time checks.
 Middleware in [Link] are functions that modify the request-response cycle, such as parsing,
logging, or error handling

1. Explain the concept of middleware in [Link].

2. What is Advanced Routing?Explain its types.

3. Explain the difference between promises and async/await in [Link].

4. Explain HTTPS.

5. What is middleware in [Link], and how is it used for request processing and error handling?

6. Explain body parsing and validation work in [Link].

7. How does non-blocking I/O work in [Link]?

8. Discuss in details working of event loop in [Link].

9. How does the event loop handle multiple requests simultaneously?

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

11. How does non-blocking I/O work in [Link]?

12. Write a NodeJs program that saves a document in Mongodb using mongoose.

13. Discuss in details working of event loop in [Link]?

1. Explain the Concept of Middleware in [Link]

Middleware in [Link] is a function that is executed during the lifecycle of a request to the
server. It has access to the request object, response object, and the next function in the
application’s request-response cycle. Middleware functions are used for tasks such as logging,
authentication, request body parsing, and error handling.
Middleware can be applied at the application level, router level, or error-handling level.
Express processes middleware in the order it is declared, so the order of middleware is
important.

Example:
javascript
Copy code
const express = require('express');
const app = express();

// Simple middleware function to log requests


[Link]((req, res, next) => {
[Link](`Request URL: ${[Link]}`);
next(); // Passes the request to the next middleware or route handler
});

// Route
[Link]('/', (req, res) => {
[Link]('Hello, world!');
});

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

2. What is Advanced Routing? Explain Its Types.

Advanced routing in [Link] refers to defining more complex and flexible routes that go
beyond basic HTTP methods and paths. It involves handling dynamic routes, route parameters,
and multiple HTTP methods.

Types of Advanced Routing in [Link] include:

 Route Parameters: Dynamic values in the URL, which can be accessed via [Link].

javascript
Copy code
[Link]('/user/:id', (req, res) => {
[Link](`User ID: ${[Link]}`);
});

 Query Strings: Data passed in the URL after the ?, accessed via [Link].

javascript
Copy code
[Link]('/search', (req, res) => {
const query = [Link].q;
[Link](`Search term: ${query}`);
});
 Handling Multiple HTTP Methods: Handling routes for different HTTP methods
(GET, POST, PUT, DELETE).

javascript
Copy code
[Link]('/profile')
.get((req, res) => [Link]('GET Profile'))
.post((req, res) => [Link]('POST Profile'));

 Middleware for Specific Routes: Using middleware only for specific routes.

javascript
Copy code
[Link]('/admin', (req, res, next) => {
[Link]('Admin route middleware');
next();
});

3. Explain the Difference Between Promises and Async/Await in [Link]

 Promises: A Promise is an object that represents the eventual completion (or failure) of
an asynchronous operation and its resulting value. A promise can be in one of three
states: pending, resolved (fulfilled), or rejected.

javascript
Copy code
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("Completed"), 1000);
});

[Link](result => [Link](result)); // Output: Completed

 Async/Await: Async and Await are syntactic sugar built on top of promises to make
asynchronous code more readable and look like synchronous code. async defines an
asynchronous function, and await pauses the execution of the function until the promise
resolves.

javascript
Copy code
async function fetchData() {
let data = await someAsyncFunction();
[Link](data);
}

The main difference is that async/await provides a more readable and synchronous-like structure
for handling asynchronous operations, while promises can result in more complex code when
multiple asynchronous operations are chained.

4. Explain HTTPS
HTTPS (HyperText Transfer Protocol Secure) is an extension of HTTP. It uses SSL/TLS
encryption to secure data transmission between the client and the server. This ensures data
privacy, integrity, and authentication. HTTPS encrypts HTTP requests and responses to prevent
eavesdropping, tampering, and man-in-the-middle attacks.

 SSL/TLS Certificate: A digital certificate that validates the identity of a website and
encrypts the data exchanged between the client and server.
 HTTPS Request: A secure connection is established over port 443 using SSL/TLS
protocols, ensuring confidentiality and data integrity.

Example of HTTPS in [Link]:


javascript
Copy code
const https = require('https');
const fs = require('fs');

const options = {
key: [Link]('[Link]'),
cert: [Link]('[Link]')
};

[Link](options, (req, res) => {


[Link](200);
[Link]('Hello, secure world!');
}).listen(3000);

5. What is Middleware in [Link], and How is it Used for Request Processing


and Error Handling?

Middleware in [Link] is used to intercept incoming requests, process them (e.g., logging,
authentication), and optionally modify the request/response before it reaches the route handler. It
can also handle errors.

 Request processing middleware: Used for tasks like request body parsing,
authentication, logging, etc.

javascript
Copy code
[Link]([Link]()); // Parses incoming JSON requests

 Error-handling middleware: These are specifically used for catching and handling
errors in your app. They have four parameters: (err, req, res, next).

javascript
Copy code
[Link]((err, req, res, next) => {
[Link](err);
[Link](500).send('Something went wrong!');
});
6. Explain Body Parsing and Validation Work in [Link]

Body Parsing: In [Link], body parsing refers to the process of converting the raw data in the
body of an HTTP request into a usable format, such as a JSON object or URL-encoded string.

Express provides built-in middleware like [Link]() and [Link]() for


this purpose.

Validation: Validation ensures that the incoming data meets certain criteria before processing.
For this, you can use packages like express-validator or Joi.

Example of Body Parsing and Validation:


javascript
Copy code
const { body, validationResult } = require('express-validator');

// Body parser
[Link]([Link]());

// Validation middleware
[Link]('/user',
body('email').isEmail().normalizeEmail(),
body('age').isInt({ min: 18 }),
(req, res) => {
const errors = validationResult(req);
if (![Link]()) {
return [Link](400).json({ errors: [Link]() });
}
[Link]('User data is valid');
}
);

7. How Does Non-blocking I/O Work in [Link]?

[Link] uses non-blocking I/O to handle asynchronous operations. Instead of waiting for tasks
like reading files or querying databases to complete, [Link] continues processing other requests
while waiting for these tasks to finish. This is achieved through an event-driven architecture and
the event loop.

When an I/O operation is requested, [Link] delegates it to the system's kernel or thread pool and
continues processing other tasks. When the I/O operation is completed, a callback function is
triggered.

8. Discuss in Detail the Working of Event Loop in [Link]

The event loop is a key feature of [Link] that allows it to handle many operations concurrently.
[Link] runs on a single thread, but it can handle multiple asynchronous operations without
blocking the execution of other tasks. The event loop manages the execution of operations and
ensures that the non-blocking I/O operations are handled asynchronously.
Steps in the event loop:

1. Timers: Executes callbacks for setTimeout and setInterval.


2. I/O Callbacks: Executes I/O tasks (e.g., network operations, database queries).
3. Idle, Prepare: Internal operations, generally for optimization.
4. Poll: Retrieves new I/O events.
5. Check: Executes setImmediate callbacks.
6. Close Callbacks: Executes the close event.

9. How Does the Event Loop Handle Multiple Requests Simultaneously?

The event loop in [Link] handles multiple requests by processing asynchronous operations (like
database queries, HTTP requests, etc.) one at a time. While [Link] waits for an I/O operation to
complete, it does not block other operations but continues to process other incoming requests.
This is achieved through callbacks, promises, and asynchronous functions.

10. Explain the Role of the Event Loop and Non-blocking I/O in [Link] with
Examples

The event loop and non-blocking I/O allow [Link] to handle concurrent operations without
blocking the main thread. This is crucial for building highly scalable applications that require
handling many I/O operations.

Example of Non-blocking I/O:


javascript
Copy code
const fs = require('fs');

[Link]('Start reading file...');


[Link]('[Link]', 'utf8', (err, data) => {
if (err) throw err;
[Link]('File content:', data);
});
[Link]('End of script.');

Here, readFile is asynchronous, so [Link] doesn't block the execution of subsequent code
while waiting for the file read operation to finish.

11. How Does Non-blocking I/O Work in [Link]?

As mentioned earlier, non-blocking I/O in [Link] means that operations like file reading,
database queries, or HTTP requests are handled asynchronously. While the system waits for I/O
to complete, other requests or operations continue to run.

12. Write a [Link] Program That Saves a Document in MongoDB Using


Mongoose
javascript
Copy code
const mongoose = require('mongoose');

[Link]('mongodb://localhost:27017/mydb', { useNewUrlParser: true,


useUnifiedTopology: true });

const Schema = [Link];

const documentSchema = new Schema({


title: String,
content: String
});

const Document = [Link]('Document', documentSchema);

const newDoc = new Document({


title: 'Sample Document',
content: 'This is a sample document saved in MongoDB.'
});

[Link]()
.then(() => [Link]('Document saved successfully'))
.catch(err => [Link]('Error saving document:', err));

13. Discuss in Detail the Working of Event Loop in [Link]

This question has already been answered above in section 8.

These explanations cover key concepts in [Link], [Link], and the workings of non-blocking
I/O, middleware, event loop, and more!

Unit - 4 MongoDB for Data Persistence


1. What is MongoDB Atlas?

2. What is Mongoose in MongoDB?

3. What does the populate() method do in Mongoose?


4. What is Mongoose in MongoDB?

5. What is MongoDB Atlas?

1. What is MongoDB Atlas?

MongoDB Atlas is a fully managed cloud database service for MongoDB. It is hosted and
operated by MongoDB, Inc. and provides automated database management, scaling, security,
and monitoring features. Atlas is designed to help developers deploy, manage, and scale
MongoDB databases on cloud platforms like AWS, Azure, and Google Cloud without having to
manually configure and manage database servers.

Some key features of MongoDB Atlas include:

 Automated backups and recovery.


 Real-time performance monitoring and alerts.
 Scalability: Ability to scale horizontally and vertically based on demand.
 Security: End-to-end encryption, IP whitelisting, and authentication.
 Global clusters: Distribution of databases across multiple regions for low-latency access.

With MongoDB Atlas, developers can focus on building applications without worrying about the
operational overhead of managing database infrastructure.

2. What is Mongoose in MongoDB?

Mongoose is an Object Data Modeling (ODM) library for MongoDB and [Link]. It provides a
schema-based solution to model the data in a MongoDB database, allowing developers to define
the structure of their data, enforce validation, and provide methods for querying and
manipulating the data.

Mongoose helps manage data relationships, query building, and data validation, making
MongoDB easier to work with in a [Link] application.

Key features of Mongoose:

 Schema-based modeling: Defines data structures and validates data before saving.
 Middleware: Supports pre- and post-hook middleware to handle asynchronous operations.
 Query building: Mongoose provides an easy-to-use query interface for CRUD operations.
 Population: Mongoose can reference and populate related data across collections.

Example of defining a schema in Mongoose:


javascript
Copy code
const mongoose = require('mongoose');
const userSchema = new [Link]({
name: String,
email: String,
age: Number
});

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

const newUser = new User({ name: 'John Doe', email: 'john@[Link]', age:
30 });
[Link]();

3. What Does the populate() Method Do in Mongoose?

The populate() method in Mongoose is used to populate fields in a document with data from
other collections. This is especially useful when working with references between collections.
For example, if a Post has a reference to a User (i.e., a user who created the post), the
populate() method can automatically fetch the associated user data when querying for posts.

The populate() method helps to retrieve and join related data in a more efficient way, without
manually performing multiple queries.

Example:
javascript
Copy code
const mongoose = require('mongoose');

const userSchema = new [Link]({ name: String });


const postSchema = new [Link]({ title: String, author: { type:
[Link], ref: 'User' } });

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


const Post = [Link]('Post', postSchema);

// Creating a user and a post


const user = new User({ name: 'Alice' });
[Link]().then(() => {
const post = new Post({ title: 'Post by Alice', author: user._id });
[Link]();
});

// Querying posts and populating the author field


[Link]()
.populate('author')
.exec((err, posts) => {
[Link](posts); // Will include full user information in the
'author' field
});

In this example, when querying the Post collection, populate('author') will automatically
replace the author field (which is just an ID) with the full user document.
4. What is Mongoose in MongoDB?

(This question is a duplicate of Question 2, and the explanation is already provided above).

5. What is MongoDB Atlas?

(This question is a duplicate of Question 1, and the explanation is already provided above).

Summary:

 MongoDB Atlas is a fully managed cloud database platform for MongoDB that simplifies
deployment, scaling, and management of MongoDB databases.
 Mongoose is an ODM library for MongoDB that simplifies data modeling and interaction with
MongoDB in [Link] applications.
 The populate() method in Mongoose is used to automatically populate referenced fields in
documents with data from related collections, streamlining complex queries involving
relationships between collections.

1. What is an aggregation pipeline in MongoDB?

2. Explain schema validation and middleware in Mongoose with example.

3. Explain Data encryption at rest and in transit in the context of mongoDB.

4. Explain authentication and authorization in a database context of mongoDB.

5. Explain schema validation and middleware in Mongoose with example.

6. Explain Data encryption at rest and in transit in the context of mongoDB.

7. Write a NodeJs program that saves a document in Mongodb using mongoose.

1. What is an Aggregation Pipeline in MongoDB?

An aggregation pipeline in MongoDB is a framework for performing advanced data processing


and transformation operations. It processes data in stages, where each stage of the pipeline
transforms the data in some way, and the output of one stage is passed as the input to the next
stage.
The aggregation pipeline is powerful for operations such as filtering, grouping, sorting, and
reshaping documents in a collection. Each stage of the pipeline is represented by a document that
defines the operation to be performed.

Common Stages in Aggregation Pipeline:

 $match: Filters documents based on a condition (similar to find()).


 $group: Groups documents by some key and performs aggregation operations (e.g., sum, avg,
count).
 $sort: Sorts the documents in the pipeline.
 $project: Reshapes documents (e.g., picking or excluding fields).
 $lookup: Joins documents from other collections.

Example of Aggregation Pipeline:


javascript
Copy code
[Link]([
{ $match: { status: 'completed' } }, // Filter completed orders
{ $group: { _id: "$customerId", totalAmount: { $sum: "$amount" } } }, //
Group by customerId and sum the amount
{ $sort: { totalAmount: -1 } } // Sort by totalAmount
descending
])

This pipeline first filters orders by status, then groups them by customerId and calculates the
total amount per customer, and finally sorts the customers by their total amount.

2. Explain Schema Validation and Middleware in Mongoose with Example

Schema Validation in Mongoose allows you to define constraints and rules for data before
saving it to the database. You can specify required fields, types, default values, custom
validation, and more.

Middleware in Mongoose are functions that are executed during specific stages of the lifecycle
of a document, such as before saving or after updating. Middleware functions can be used to
perform actions like hashing passwords, logging, or setting default values.

Example of Schema Validation and Middleware:


javascript
Copy code
const mongoose = require('mongoose');

// Schema definition with validation


const userSchema = new [Link]({
name: {
type: String,
required: true, // Validation: Name must be provided
},
email: {
type: String,
required: true,
unique: true, // Validation: Email must be unique
validate: {
validator: (v) => /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-
Z]{2,7}$/.test(v),
message: props => `${[Link]} is not a valid email!`
}
},
age: {
type: Number,
min: [18, 'Age must be 18 or older'], // Validation: Age must be >= 18
}
});

// Middleware example: Pre-save hook


[Link]('save', function(next) {
if ([Link]) {
[Link]('New user being saved');
}
next(); // Continue with the save operation
});

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

const newUser = new User({ name: 'John Doe', email: '[Link]@[Link]',


age: 25 });

[Link]()
.then(() => [Link]('User saved'))
.catch(err => [Link]('Error saving user:', err));

In this example:

 The schema enforces validation for name, email, and age.


 The pre('save') middleware runs before saving the document to the database, and you can
use it to perform custom actions (e.g., logging).

3. Explain Data Encryption at Rest and in Transit in the Context of MongoDB

 Encryption at Rest: This refers to encrypting data stored on disk (i.e., the data stored in
MongoDB files on disk). It ensures that sensitive data is protected in case the physical
storage media is compromised.
o MongoDB provides encryption at rest through the Encrypted Storage Engine which uses
the Key Management Interoperability Protocol (KMIP) for managing encryption keys.
o Encryption at rest is important to protect data in storage, especially when dealing with
compliance regulations such as HIPAA or GDPR.
 Encryption in Transit: This refers to encrypting data while it is being transmitted over
the network (i.e., between the MongoDB client and the database server). It prevents
sensitive data from being exposed during transmission, especially in untrusted networks.
o TLS/SSL is used to encrypt the communication between clients and MongoDB servers.
o Enabling TLS/SSL encryption ensures that all data exchanged between clients and
servers is encrypted, reducing the risk of man-in-the-middle (MITM) attacks.

Both encryption at rest and in transit are essential for securing sensitive data and ensuring
privacy and integrity.

4. Explain Authentication and Authorization in the Context of MongoDB

 Authentication: This is the process of verifying the identity of users or applications


trying to access the MongoDB database. MongoDB supports various authentication
mechanisms, including:
o Username and Password Authentication: The most common form, where users must
provide valid credentials to authenticate.
o Kerberos Authentication: Used in enterprise environments for more secure
authentication.
o x.509 Certificates: Used for SSL-based authentication.

MongoDB stores user credentials in the admin database or the application database.

 Authorization: Once authenticated, authorization determines what actions a user or


application can perform on the database. MongoDB uses role-based access control
(RBAC) to assign specific roles to users, such as:
o read: Allows reading data from the database.
o readWrite: Allows reading and writing data.
o dbAdmin: Grants administrative rights on the database.
o root: Full administrative access to the MongoDB instance.

MongoDB enables you to configure roles for different users and restrict access based on the
principle of least privilege.

Example of Creating a User with Authentication and Authorization in MongoDB:


javascript
Copy code
[Link]({
user: "adminUser",
pwd: "password123",
roles: [
{ role: "readWrite", db: "myDatabase" },
{ role: "dbAdmin", db: "myDatabase" }
]
});
In this example, the adminUser can read, write, and administer the myDatabase.

5. Explain Schema Validation and Middleware in Mongoose with Example

(This question is a duplicate of Question 2, which has already been answered above.)

6. Explain Data Encryption at Rest and in Transit in the Context of MongoDB

(This question is a duplicate of Question 3, which has already been answered above.)

7. Write a [Link] Program That Saves a Document in MongoDB Using


Mongoose
javascript
Copy code
const mongoose = require('mongoose');

// Connect to MongoDB
[Link]('mongodb://localhost:27017/mydatabase', {
useNewUrlParser: true,
useUnifiedTopology: true
});

// Define a schema
const documentSchema = new [Link]({
title: String,
content: String
});

// Create a model from the schema


const Document = [Link]('Document', documentSchema);

// Create a new document


const newDocument = new Document({
title: 'Sample Document',
content: 'This is a sample document saved in MongoDB.'
});

// Save the document


[Link]()
.then(() => {
[Link]('Document saved successfully');
[Link]();
})
.catch((err) => {
[Link]('Error saving document:', err);
});

In this example:

 We connect to a MongoDB database using [Link].


 A schema and model are defined for a Document collection.
 A new document is created and saved using the .save() method.

Summary:

 Aggregation Pipeline: A MongoDB feature to process data in multiple stages.


 Schema Validation & Middleware: Mongoose helps enforce data integrity and allows pre/post-
save actions.
 Data Encryption: Protects data both at rest (on disk) and in transit (during communication).
 Authentication & Authorization: Ensures secure access control in MongoDB using
authentication methods and role-based access control.

Unit - 5 Advanced Topics and Best Practices


2 Marks Question

1. List the tool for unit testing in web applications.

2. Define code splitting in web development.

3. List the tool for end to end testing in web applications

1. List the Tool for Unit Testing in Web Applications:

Some common tools used for unit testing in web applications are:

 Jest: A JavaScript testing framework, often used with React applications.


 Mocha: A flexible test framework for [Link] and JavaScript.
 Chai: An assertion library often used in conjunction with Mocha.
 Jasmine: A behavior-driven testing framework for JavaScript.
 Karma: A test runner that works with frameworks like Jasmine, Mocha, etc.
 AVA: A test runner for JavaScript, designed for simplicity and performance.
 QUnit: A JavaScript unit testing framework.

2. Define Code Splitting in Web Development:

Code splitting is a technique in web development that involves breaking up the codebase into
smaller bundles or chunks that can be loaded on-demand, rather than loading the entire codebase
at once. This helps improve the initial loading time and performance of web applications.

Advantages of Code Splitting:

 Faster loading times: Only necessary code is loaded when needed, improving the initial
load time.
 Efficient use of resources: Non-essential code is only loaded when required.
 Improved user experience: Reduces the time users wait for the application to load.

Code splitting is often implemented with bundlers like Webpack or Parcel.

3. List the Tool for End-to-End Testing in Web Applications:

Some common tools for end-to-end (E2E) testing in web applications are:

 Cypress: A modern E2E testing framework for web applications, known for its speed and
ease of use.
 Selenium: A popular web automation tool for E2E testing, compatible with multiple
browsers and programming languages.
 Playwright: A testing framework for automating browsers, similar to Selenium but with
more modern features.
 Puppeteer: A [Link] library for automating Chrome and Chromium, often used for E2E
testing.
 TestCafe: A framework for E2E testing that doesn’t require browser plugins.
 [Link]: A testing framework based on [Link] and Selenium for automating E2E
tests.

Each of these tools is used to simulate user interactions with a web application, testing its overall
functionality from start to finish.

5 Marks Question
1. Define code splitting in web development.

2. Explain the Need for security in Angular and XSS, CSRF prevention

1. Define Code Splitting in Web Development

Code splitting is a technique used in web development to improve the performance of web
applications by splitting the large JavaScript codebase into smaller chunks or bundles. These
smaller bundles can then be loaded on demand, rather than loading the entire application upfront.
This method ensures that only the necessary code is loaded for the current page or feature,
improving the initial loading time of the application.

Key Concepts in Code Splitting:

 Chunks: The smaller parts that the application is divided into. They can be loaded dynamically
when required.
 Lazy Loading: Code splitting often works in conjunction with lazy loading, where chunks are only
loaded when a user interacts with the application (e.g., when navigating to a different page).
 Entry Points: These are the parts of the application where code splitting occurs. For example,
routes or features that are loaded only when the user visits them.

Benefits of Code Splitting:

 Improved Initial Load Time: Since only the necessary code is loaded on startup, the application
loads faster.
 Reduced Memory Usage: As only required chunks are loaded, the browser’s memory usage is
optimized.
 Better User Experience: Faster load times and responsiveness lead to a better overall user
experience.

Example of Code Splitting in Webpack:

In Webpack, code splitting can be achieved using import() statements:

javascript
Copy code
// This will split the code into two chunks
const loadComponent = () => import('./Component');

When a user navigates to the specific page or feature, the component will be loaded dynamically.

2. Explain the Need for Security in Angular and XSS, CSRF Prevention
Security is a critical aspect of any web application, especially when it deals with sensitive user
data. Angular, being a popular front-end framework, provides built-in tools and practices to
secure applications. However, developers need to understand and implement various security
measures to protect the application from common web vulnerabilities like Cross-Site Scripting
(XSS) and Cross-Site Request Forgery (CSRF).

Need for Security in Angular:

Angular provides a secure environment for web development through features like sanitization,
content security policy, and security best practices. However, developers must still be aware
of threats and implement additional measures where necessary to ensure the application's
integrity, protect user data, and maintain trust.

1. Cross-Site Scripting (XSS) Prevention:

XSS is a vulnerability that occurs when an attacker injects malicious scripts into web pages
viewed by other users. These scripts can steal cookies, session data, or perform actions on behalf
of the user without their consent.

Angular prevents XSS attacks by:

 Automatic escaping of data: Angular automatically escapes HTML content to prevent malicious
scripts from executing in templates.
 Sanitization: Angular sanitizes potentially dangerous data before rendering it in the browser. It
ensures that HTML, JavaScript, and CSS inserted into the DOM are safe to execute.

For example, Angular uses DomSanitizer to prevent unsafe content from being rendered:

typescript
Copy code
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';

constructor(private sanitizer: DomSanitizer) {}

sanitizeHtml(content: string): SafeHtml {


return [Link](content);
}

In this case, bypassSecurityTrustHtml sanitizes the input and ensures it's safe before
rendering it.

2. Cross-Site Request Forgery (CSRF) Prevention:

CSRF is an attack where an attacker tricks the user into performing unwanted actions on a web
application where the user is authenticated, like making a purchase or changing account settings.

To prevent CSRF in Angular, it is important to:


 Use CSRF Tokens: Angular uses HTTP interceptors to add a token to each HTTP request that
requires protection from CSRF attacks. These tokens are typically sent with the request and
checked on the server side to ensure that the request is legitimate.

How CSRF Protection Works in Angular:

1. The server generates a CSRF token and stores it in the session or as a cookie.
2. The token is included in each form or AJAX request sent by Angular via an HTTP interceptor.
3. The server checks the CSRF token on incoming requests and validates it before processing.

Example of CSRF token implementation in Angular:

typescript
Copy code
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler } from
'@angular/common/http';

@Injectable()
export class CsrfInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
// Assuming CSRF token is stored in a cookie or local storage
const csrfToken = [Link]('csrfToken');

const clonedRequest = [Link]({


setHeaders: {
'X-CSRF-Token': csrfToken || ''
}
});

return [Link](clonedRequest);
}
}

In this example, the CSRF token is added to the headers of each request using an HTTP
interceptor.

Summary of Security Measures in Angular:

 XSS Protection: Angular automatically sanitizes inputs to prevent the execution of malicious
scripts, ensuring that untrusted data is handled safely.
 CSRF Protection: CSRF tokens are used to verify that requests are legitimate, ensuring the
authenticity of user actions.

By utilizing Angular's built-in security mechanisms and adhering to best practices, developers
can prevent common attacks like XSS and CSRF, ensuring the safety of their web applications.

You might also like