You are on page 1of 33

Introduction

RxJS is a library for composing asynchronous and event-based


programs by using observable sequences. It provides one core type,
the Observable , satellite types (Observer, Schedulers, Subjects) and
operators inspired by Array methods (map, filter, reduce, every, etc)
to allow handling asynchronous events as collections.

Think of RxJS as Lodash for events.

ReactiveX combines the Observer pattern with the Iterator


pattern and functional programming with collections to fill the need
for an ideal way of managing sequences of events.

The essential concepts in RxJS which solve async event management


are:

 Observable: represents the idea of an invokable collection of


future values or events.
 Observer: is a collection of callbacks that knows how to listen to
values delivered by the Observable.
 Subscription: represents the execution of an Observable, is
primarily useful for cancelling the execution.
 Operators: are pure functions that enable a functional
programming style of dealing with collections with operations
like map, filter, concat, reduce, etc.
 Subject: is equivalent to an EventEmitter, and the only way of
multicasting a value or event to multiple Observers.
 Schedulers: are centralized dispatchers to control concurrency,
allowing us to coordinate when computation happens on
e.g. setTimeout or requestAnimationFrame or others.

First examples

Normally you register event listeners.

content_copyopen_in_newdocument.addEventListener('click', ()
=> console.log('Clicked!'));

Using RxJS you create an observable instead.

content_copyopen_in_newimport { fromEvent } from 'rxjs';


fromEvent(document, 'click').subscribe(() =>
console.log('Clicked!'));

Purity

What makes RxJS powerful is its ability to produce values using pure
functions. That means your code is less prone to errors.

Normally you would create an impure function, where other pieces of


your code can mess up your state.

content_copyopen_in_newlet count = 0;

document.addEventListener('click', () => console.log(`Clicked


${++count} times`));

Using RxJS you isolate the state.

content_copyopen_in_newimport { fromEvent, scan } from 'rxjs';

fromEvent(document, 'click')

.pipe(scan((count) => count + 1, 0))

.subscribe((count) => console.log(`Clicked ${count}


times`));

The scan operator works just like reduce for arrays. It takes a value
which is exposed to a callback. The returned value of the callback will
then become the next value exposed the next time the callback runs.

Flow

RxJS has a whole range of operators that helps you control how the
events flow through your observables.

This is how you would allow at most one click per second, with plain
JavaScript:

content_copyopen_in_newlet count = 0;

let rate = 1000;

let lastClick = Date.now() - rate;

document.addEventListener('click', () => {
if (Date.now() - lastClick >= rate) {

console.log(`Clicked ${++count} times`);

lastClick = Date.now();

});

With RxJS:

content_copyopen_in_newimport { fromEvent, throttleTime, scan


} from 'rxjs';

fromEvent(document, 'click')

.pipe(

throttleTime(1000),

scan((count) => count + 1, 0)

.subscribe((count) => console.log(`Clicked ${count}


times`));

Other flow control operators


are filter, delay, debounceTime, take, takeUntil, distinct, distinctUn
tilChanged etc.

Values

You can transform the values passed through your observables.

Here's how you can add the current mouse x position for every click, in
plain JavaScript:

content_copyopen_in_newlet count = 0;

const rate = 1000;

let lastClick = Date.now() - rate;

document.addEventListener('click', (event) => {

if (Date.now() - lastClick >= rate) {


count += event.clientX;

console.log(count);

lastClick = Date.now();

});

With RxJS:

content_copyopen_in_newimport { fromEvent, throttleTime, map,


scan } from 'rxjs';

fromEvent(document, 'click')

.pipe(

throttleTime(1000),

map((event) => event.clientX),

scan((count, clientX) => count + clientX, 0)

.subscribe((count) => console.log(count));

What are RxJS Operators?


Taken straight from the RxJS manual:
Operators are the essential pieces that allow complex asynchronous code to be easily
composed in a declarative manner.

If you're scratching your head, don't worry. I think most people would be confused by that
statement alone. Luckily for us, the manual gives an even better definition:

An Operator is a function which creates a new Observable based on the current Observable.
This is a pure operation: the previous Observable stays unmodified.

Essentially, an Operator is like a machine that takes an Observable as an input, performs


some logic on the values streamed through the Observable, and creates a new Observable
with these values, without changing the original Observable.
The diagram below might help illustrate it a little better.
We can see that the Operator takes in the values from one Observable, and creates a new
Observable that emits altered values of the original Observable's values, without affecting
the original Observable.

Now let's take a look at 6 basic Operators: of, from, map, tap, switchMap, take.

🔗1. of - Creation Operator


The of Operator is a creation Operator. Creation Operators are functions that create an
Observable stream from a source.
The of Operator will create an Observable that emits a variable amount of values in
sequence, followed by a Completion notification.
A Completion notification tells the Observable's subscribers that the Observable will no
longer be emitting new values. We will cover this in more detail in a future article!
Let's take a look at of in practice.
const arr = [1, 2, 3];

const arr$ = of(arr);

arr$.subscribe((values) => console.log(`Emitted Values: `, values));


of creates the Observable, and when we subscribe to it, it starts emitting its values
immediately.
The output of the above is:

Emitted Values: [1, 2, 3]


of will emit the full array [1, 2, 3] as a full value. This is in contrast to from, which we will
look at next!

🔗2. from - Creation Operator


The from Operator turns an Array, Promise, or Iterable, into an Observable.
This operator will convert a Promise to an Observable, allowing for it to be handled in a more
reactive manner. When the Promise resolves or rejects, a completion notification will be sent
to any subscribers.

Also, unlike of, it will emit each element in an Array or Iterable in sequence, rather than the
full value. Once all elements of the Array or Iterable have been emitted, a completion
notification is sent to any subscribers.
Let's take the example we used for of to see this difference in action:
const arr = [1, 2, 3];

const arr$ = from(arr);

arr$.subscribe((values) => console.log(`Emitted Values: `, values));


Its output is:

Emitted Values: 1
Emitted Values: 2
Emitted Values: 3
As we can see by the multiple logs, the from Operator took each number and emitted it as a
value. The subscriber received each value in sequence, and called console.log three
times.
We can also use a value such as a string:

const fromString$ = from("Hello");


fromString$.subscribe((value) => console.log(`Emitted Values: `, value));
The output is:

Emitted Values: H
Emitted Values: e
Emitted Values: l
Emitted Values: l
Emitted Values: o
How about for a Promise? Let's take a look!

const examplePromise = new Promise((resolve, reject) => {


// Do some async code and resolve and object with an id property
return resolve({ id: 1 });
});

const promise$ = from(examplePromise);


promise$.subscribe((value) => console.log(`Emitted Values: `, value));
The output of this would be:

Emitted Values: {id: 1}


When the Promise resolves, the value gets emitted as the next value in the Observable.

🔗3. map - Transformation Operator


The map operator is a Transformation Operator. It takes values from one Observable,
transforms them, and creates a new Observable that emits the transformed values.
With map, you can perform simple transformations to the values emitted by an Observable.
Let's take a look at two examples.
For the first example, we'll take the Array example for the from Operator, and modify it to
also use map:
const arr = [1, 2, 3];

const fromArr$ = from(arr);

fromArr$
.pipe(map((value) => value + 10))
.subscribe((value) => console.log(`Emitted Values: `, value));
You'll notice the introduction of the .pipe() call. This is RxJS's method for applying
operators to an Observable's stream before you subscribe to it. It will pipe the value emitted
from the Observable through each operator passed as an argument, before passing the final
transformed value to the subscribe method. We'll cover this in more detail in a future
article!
In this example, as map is a transformation Operator, it must be used within the .pipe() call
so that it can transform the value it receives from the Observable. We are simply adding 10
to the value, and emitting the transformed value.
You can see this in the output:

Emitted Values: 11
Emitted Values: 12
Emitted Values: 13
We can do almost anything in the map Operator, but a common use-case would be to get a
property from an object that is emitted in an Observable stream. We can use our Promise
example to see this in action:
const examplePromise = new Promise((resolve, reject) => {
// Do some async code and resolve and object with an id property
return resolve({ id: 1 });
});

const promise$ = from(examplePromise);


promise$
.pipe(map((obj) => obj.id))
.subscribe((value) => console.log(`Emitted Values: `, value));
Here, we are telling the map operator to return the id property of the object that is resolved in
the Promise. The output of this is:
Emitted Values: 1
The map Operator is a commonly used Operator and is very useful for a number of use-
cases!

🔗4. switchMap - Transformation Operator


The switchMap operator is another transformation Operator.
switchMap receives the values emitted by an Observable, and then returns a new
Observable from a different source.
Let's say you have an Observable that emits User IDs. You may want to fetch the full User
object correlating to the ID, then do something with the full details. The switchMap operator
would receive the ID from the Observable, then return an Observable containing the
response from the request to fetch the User object.
I find it can be useful to think of this in the terms of switching streams. You're switching
from one Observable stream to another.
Let's take a look at an example:

const userDetails$ = from(this.userService.getActiveUserID())


.pipe(switchMap(id => this.userService.fetchUserForID(id)))
.subscribe(user => console.log("Found user ", user));
Here, we ask for the active user's ID. Then, we ask the userService to make an ajax
request to our backend to fetch the User that correlates with the ID. We are assuming that
the fetchUserForID call returns an Observable. (This can be possible with
the ajax operator which we will discuss in a future article!)
We then subscribe to this new Observable stream, and receive the value it emits, rather than
the values emitted from from(this.userService.getActiveUserID()) as seen in the
output:
Found user {id: 1, name: "Test User", email: "test@test.com"}
It's worth noting that the switchMap operator will cancel any in-flight network requests if it
receives a new value from the original (commonly known as the source) Observable stream,
making it a great candidate for typeahead search implementations!

🔗5. tap - Utility Operator


The tap Operator is a Utility Operator which is very similar to a helper function, except in the
reactive programming landscape.
tap allows you to perform actions or side effects on an Observable
stream without modifying or altering the original stream. The values "pass-through"
the tap Operator to the next Operator or Subscriber.
This can be very useful for logging:

const arr = [1, 2, 3];

const fromArr$ = from(arr);

fromArr$
.pipe(tap((value) => console.log("Received value: ", value)))
.subscribe((value) => console.log(`Emitted Values: `, value));
Which would output:

Received value: 1
Emitted Values: 1

Received value: 2
Emitted Values: 2

Received value: 3
Emitted Values: 3

🔗6. take - Filtering Operator


The take operator is a Filtering Operator. Filtering Operators allows you to select how and
when to accept values emitted from Observables.
take is one of the most common and most simplistic filtering Operators. It allows you to
specify a maximum number of values you want to receive from an Observable.
We can use our from example where we emit the elements of an Array, and combine it
with take to get a better understanding of this operator:
const arr = [1, 2, 3];

const fromArr$ = from(arr);

fromArr$
.pipe(take(1))
.subscribe((value) => console.log(`Emitted Values: `, value));
From the output below we can see we only received and used 1 value from the array:

Emitted Values: 1
It can be used in situations where we want to limit how many user-produced events
(fromEvent) we want to handle, for example, the first time the user clicks in our app

RxJs Interview Questions.

These are some common RxJs interview questions.

What is RxJS ?

It's an acronym for Reactive Extensions of JavaScript. and it's a JavaScript library for
handling Asynchronous data streams and events.

What is Stream ?

Values of data over time.

What is Reactive Programming?

It's a programming paradigm that deals with asynchronous streams of data.

What are the advantages of Reactive Programming?

 Easy to handle streams of data.


 Has many useful operators that can save time: switchMap, concatMap.
 Helps avoid callback hell.
 Makes complex threading easy.
 Cleaner & maintainable code.

What do you understand by the term Non-Blocking in RxJS?

It's an algorithm that does not allow threads competing for the same resource to be
indefinitely postponed through mutual exclusion of the resource.

What is Back-Pressure in Reactive Programming?

It's the resistance(opposing force) on the desired data flow of an application.

What is an Obserable?

It's an object that emits values over time.


What is the difference between an observable and a Promise?

Promise:

 A promise has a single callback at the end of completion or failure.


 A promise is not Lazy. It cannot be cancelled.

Observable:

 An observable emits multiple values over time.


 You may cancel an obeservable with an Unsubscribe() method.
 An observable only executes once subscribed to it.
 Provides efficient operators: map, reduce, foreach, filter, reduce, retry, retryWhen.

What is the difference between Cold and Hot Observables ?

 Cold observables have their data produced inside the observable.

 Hot observables have their data produced outside the observable.

 Cold Observables only emit data once subscribed to;

 Hot Observables emit values even before the subscription is made. Used when
sharing data among many subscribers.

What are RxJS Operators ?

 These are methods that can be applied to the observable in order to modify the data
stream.

What is Observers and Subscriptions ?

 Observers: They are the listeners/ consumers of the data stream; Observers listen
/subscribe to the data stream.

 Subscribers: - Objects returned when an observable is subscribed; Useful in


canceling the subscription.

What is Subject ?

 It's a type of observable where data is multicasted to its observables.

What are different types of Subject ?

 Behaviour Subject & Replay Subject.


 Subject: -Doesn't revive data prior to their subscription.

 Behaviour Subject: - Emits last value to all & new observers.

 Replay Subject: - All observers will revive data prior to their subscription; uses a
buffer to hold values and re-emits values on new subscriptions.

What are Schedulers:

A scheduler controls the execution of when the subscription has to start and be notified.

Types of schedulers: queueScheduler, asapScheduler, asyncScheduler,


animationFrameScheduler

What is RxJS Map and What is Higher-Order Observable Mapping?

 RxJS Map: It's a flattening operator used to transform current emitted data values to
the desired data format.

const http$ : Observable<Books[]> = this.http.get('/api/books');

http$
.pipe(
tap(() => console.log('HTTP request executed')),
map(res => Object.values(res['payload']))
)
.subscribe(
books => console.log("books", books)
);

 Higher-Order Mapping: These are Rxjs operators used to map source observable
values into other observables.

When do we use the switchMap, mergeMap and concatMap?

i) What is RxJS ConcatMap?


 Concat: Joins multiple Observables together, by subscribing to them one at a time
and merging their results into the output Observable.

 Used to combine multiple HTTP requests.

 ConcatMap: Projects each source value to an Observable which is merged in the


output Observable, in a serialized fashion waiting for each one to complete before
merging the next.

Why would you want to use ConcatMap?

 Used to combine multiple HTTP requests; alleviating the need for nested subscribers.
 All HTTP requests are sent to the backend sequentially; Once the previous request
has been completed.

this.form.valueChanges
.pipe(
concatMap(formValue => this.http.put("/api/book/",formValue))
)
.subscribe(
response => ... handle successful ...,
err => ... handle error ...
);
ii) What is RxJS mergeMap?

 MergeMap:Projects each source value to an Observable which is merged in the


output Observable.
 Its operation is in parallel, unlike concatMap, it's not sequential in nature.

this.form.valueChanges
.pipe(
mergeMap(formValue =>
this.http.put("/api/book/", formValue))
)
.subscribe(
res => ... handle successful response ...,
err => ... handle error ...
);
iii) What is RxJS switchMap?

 switchMap: An operator that combines source values into an output observable that
represents the most recent projected observable.

 In switching, unlike merging, we'll unsubscribe the previous Observable before


subscribing to the new Observable if the new Observable begins to emit the values.

Why would you want to use SwitchMap?

 When you want to get the most rescent updated values the second source
anticipated to delay.

UseCase:
a) Update data from local cache or CDN before retrieving from backend.

const searchText$: Observable<string> =


fromEvent<any>(this.input.nativeElement, "keyup")
.pipe(
map(event => event.target.value), // map to form input component
value
startWith(""), // avoid spaces
debounceTime(400), // delay request by 400 ms to avoid sending
multiple request while user still typing
distinctUntilChanged() // prevent duplicate request on retype
);

const lessons$: Observable<Lesson[]> = searchText$


.pipe(
switchMap(search => (){
const params = new HttpParams().set("search", search);
return this.http.get("/api/book/", {params});
)
)
.subscribe();

iii) What is RxJS exhaustMap?

 exhaust: Converts a higher-order Observable into a first-order Observable by


dropping inner Observables while the previous inner Observable has not yet
completed.

 It behaves like mergeAll. However, exhaust ignores every new inner Observable if the
previous Observable has not yet completed. Once that one completes, it will accept
and flatten the next inner Observable and repeat this process.
 ExhaustMap: Projects each source value to an Observable which is merged in the
output Observable only if the previous projected Observable has completed.

const clicks = fromEvent(document, 'click');


const result = clicks.pipe(
exhaustMap(ev => interval(1000).pipe(take(5)))
);
result.subscribe(x => console.log(x));
When we use zip and combineLatest and withLatestFrom ?

 Zip: Combines multiple Observables to create an Observable whose values are


calculated from the values, in order, of each of its input Observables.

import { zip, of } from 'rxjs';


import { map } from 'rxjs/operators';

let age$ = of<number>(27, 25, 29);


let name$ = of<string>('Foo', 'Bar', 'Beer');
let isDev$ = of<boolean>(true, true, false);

zip(age$, name$, isDev$).pipe(


map(([age, name, isDev]) => ({ age, name, isDev })),
)
.subscribe(x => console.log(x));

// outputs
// { age: 27, name: 'Foo', isDev: true }
// { age: 25, name: 'Bar', isDev: true }
// { age: 29, name: 'Beer', isDev: false }

 combineLatest: Combines multiple Observables to create an Observable whose


values are calculated from the latest values of each of its input Observables.

import { combineLatest, of } from 'rxjs';


import { delay, starWith } from 'rxjs/operators';

const observables = [1, 5, 10].map(


n => of(n).pipe(
delay(n * 1000), // emit 0 and then emit n after n seconds
startWith(0),
)
);
const combined = combineLatest(observables);
combined.subscribe(value => console.log(value));
// Logs
// [0, 0, 0] immediately
// [1, 0, 0] after 1s
// [1, 5, 0] after 5s
// [1, 5, 10] after 10s

 withLatestFrom: Combines the source Observable with other Observables to create


an Observable whose values are calculated from the latest values of each, only when
the source emits.

import { fromEvent, interval } from 'rxjs';


import { withLatestFrom } from 'rxjs/operators';

const clicks = fromEvent(document, 'click');


const timer = interval(1000);
const result = clicks.pipe(withLatestFrom(timer));
result.subscribe(x => console.log(x));

Redux

What is Redux?

Open-Source JavaScript library for managing application state. Used in frontend framework
such as React, Angular & Rxjs

What are the core principles of Redux?

-Single source of Truth: All application data is stored in a single object tree.

 State is read only: The state is immutable.


 State can only be change with Pure Functions: These pure functions are
called Reduces and they specify how the object tree is should be updated.

Is there any similarity between Redux and RxJS?

 Redux uses reactive paradigm to mutate state of the store.


 RxJs uses reactive paradigm to accomplish asynchronous data processing.
What is the difference between Reactive Programming and Imperative Programming?

 Reactive programming is a programming paradime where data is being Pushed to


subscribed observers in an application. Where as:
 Imperative programming is a programming paradime where data is
being Pulled on request from an application.

What is the difference between BehaviorSubject and Observable in RxJS?

 Observable is a consumer/listener while a BehaviourSubject is a synchronous data


source that emits data to observers.
 Observables are stateless while BehaviourSubject is stateful.
 Observables create a copy of the data while BehaviourSubject emits data to
observers.
 Observables are unidirectional in nature while BehaviorSubject is bi-directional in
nature.

Q4. What is an Observable in RxJS?

A4. An Observable in RxJS is a core primitive representing a lazy, push-based collection that
can emit multiple values over time. It serves as a blueprint for creating and managing data
streams, allowing developers to handle asynchronous operations more effectively.
Observables are lazy by nature, meaning they do not start emitting values until a subscriber
actively listens for them. An Observable can emit three types of values: onNext (data),
onError (error), and onCompleted (completion).

Q5. How are Observables used in Angular applications?

A5. Observables are used in various aspects of Angular applications to manage


asynchronous tasks, such as:

o Handling HTTP requests with the HttpClient module


o Managing user interactions, such as button clicks and form submissions
o Managing state changes in reactive forms
o Building custom state management solutions, like NgRx
o Handling real-time data streams with WebSockets

Q6. What are the key differences between Observables and Promises?

A6. Observables and Promises are both used for handling asynchronous operations, but they
have some key differences:

Observables Promises
Can emit multiple values over time Emit a single value
Lazy and only execute when subscribed Eagerly execute upon creation
Can be canceled via unsubscription Cannot be canceled
Support various transformation methods Limited transformation capabilities

B. Creating and Subscribing to Observables

Q7. How do you create an Observable in RxJS?

A7. To create an Observable in RxJS, you can use the Observable class and the create()
method. Inside the create() method, you define the logic for emitting values, handling errors,
and notifying subscribers of completion. Here's an example:

import { Observable } from 'rxjs'; const myObservable = new Observable((observer) =>


{ observer.next('First value'); observer.next('Second value'); setTimeout(() =>
{ observer.next('Value after delay'); observer.complete(); }, 2000); });

Q8. How do you subscribe to an Observable in Angular?

A8. To subscribe to an Observable in Angular, you use the subscribe() method, providing
callbacks for handling data, errors, and completion. Here's an example:

myObservable.subscribe( (data) => console.log('Data:', data), (error) =>


console.log('Error:', error), () => console.log('Completed') );

Q9. How can you unsubscribe from an Observable?

A9. To unsubscribe from an Observable, you can call the unsubscribe() method on the
subscription object returned by the subscribe() method. This is important to prevent memory
leaks, especially when working with long-lived subscriptions. Example:

const subscription = myObservable.subscribe(/* ... */); subscription.unsubscribe();

C. Operators and Transformation

Q10. What are RxJS operators?

A10. RxJS operators are functions that allow developers to manipulate and transform
Observable streams. They can be used for tasks like filtering, mapping, combining, and error
handling. Operators are categorized as creation, transformation, filtering, combination,
multicasting, error handling, and utility operators.
Q11. What is the purpose of the pipe() function in RxJS?

A11. The pipe() function in RxJS is used to chain multiple operators together, allowing you to
apply a series of transformations to an Observable stream. The pipe() function takes one or
more operator functions as arguments and returns a new Observable with the applied
transformations.

Q12. Can you provide some examples of commonly used RxJS operators in Angular
applications?

A12 (Continued). Some commonly used RxJS operators in Angular applications include:

o map: Transforms the values emitted by an Observable by applying a specified


function to each value.
o filter: Filters out values emitted by an Observable based on a specified condition.
o catchError: Catches errors that occur during the processing of an Observable and
allows for handling or recovery.
o switchMap: Maps each value to an Observable and switches to the latest emitted
Observable, canceling previous subscriptions.
o mergeMap: Maps each value to an Observable and merges the resulting Observables
into a single output Observable.
o concatMap: Maps each value to an Observable and concatenates the resulting
Observables in order, waiting for the previous Observable to complete before
subscribing to the next one.
o debounceTime: Delays the emission of values from an Observable, ensuring a
specified amount of time passes between each emitted value.
o take: Emits only the first specified number of values from an Observable and then
completes.
o takeUntil: Emits values from an Observable until a specified notifier Observable emits
a value.

Here's an example of using multiple operators with the pipe() function:

import { of } from 'rxjs'; import { map, filter } from 'rxjs/operators'; const


sourceObservable = of(1, 2, 3, 4, 5); const transformedObservable =
sourceObservable.pipe( map(value => value * 2), filter(value => value > 4) );
transformedObservable.subscribe( (data) => console.log('Data:', data), (error) =>
console.log('Error:', error), () => console.log('Completed') );

In this example, the sourceObservable emits values 1 through 5. The transformedObservable


applies the map and filter operators, resulting in the values 6 and 8 being emitted.
D. Error Handling and Retry Mechanisms

Q13. How do you handle errors in RxJS?

A13. In RxJS, you handle errors using the catchError operator, which intercepts errors emitted
by an Observable and allows you to handle or recover from them. You can provide a function
that either returns a new Observable or throws an error. Here's an example:

import { of } from 'rxjs'; import { catchError, map } from 'rxjs/operators'; const


sourceObservable = of(1, 2, 3, 4, 5); const errorObservable =
sourceObservable.pipe( map(value => { if (value === 3) { throw new Error('Error on
value 3'); } return value; }), catchError(error => { console.error('Caught error:',
error.message); return of('Recovered value'); }) ); errorObservable.subscribe( (data) =>
console.log('Data:', data), (error) => console.log('Error:', error), () =>
console.log('Completed') );

Q14. How can you implement a retry mechanism for failed HTTP requests in Angular using
RxJS?

A14. You can implement a retry mechanism for failed HTTP requests in Angular using the
retry or retryWhen operators from RxJS. The retry operator automatically resubscribes to the
source Observable a specified number of times when an error occurs. The retryWhen
operator allows you to define more complex retry strategies based on custom logic. Here's
an example using the retry operator:

import { HttpClient } from '@angular/common/http'; import { retry } from


'rxjs/operators'; // ... constructor(private httpClient: HttpClient) {} fetchData()
{ this.httpClient.get('https://api.example.com/data').pipe( retry(3) // Retry the request
up to 3 times if it fails ).subscribe( (data) => console.log('Data:', data), (error) =>
console.log('Error:', error), () => console.log('Completed') ); }

E. Subjects and Multicasting

Q15. What is a Subject in RxJS?

A15. A Subject in RxJS is a special type of Observable that also acts as an Observer. It can
both emit values and subscribe to other Observables. Subjects can multicast values to
multiple subscribers, making them useful for scenarios where you need to share a single data
stream with multiple consumers. Subjects can also be used for implementing event buses or
broadcasting data to different parts of your application.
Q16. How do Subjects differ from Observables?

A16. The main differences between Subjects and Observables are:

1. Subjects can act as both Observables and Observers, while Observables can only emit
values.
2. Subjects can multicast, meaning they can emit values to multiple subscribers
simultaneously, while Observables are unicast by default.

Q17. What are the different types of Subjects in RxJS?

A17. RxJS provides four types of Subjects:

1. Subject: The basic Subject, which can multicast and act as both an Observable and
Observer.
2. BehaviorSubject: A variant of Subject that stores the latest value it has emitted, and it
will provide this value to new subscribers immediately upon subscription.
3. ReplaySubject: A variant of Subject that records a specified number of emitted values
and provides them to new subscribers upon subscription.
4. AsyncSubject: A variant of Subject that emits only the last value and only when the
source Observable completes. It is useful for caching results of HTTP requests or
other asynchronous operations.

F. Higher-order Observables

Q18. What is a higher-order Observable?

A18. A higher-order Observable is an Observable that emits other Observables. It is used to


manage complex, nested asynchronous operations in reactive programming. In other words,
a higher-order Observable is an Observable that produces other Observables instead of
emitting primitive data types like numbers or strings.

Higher-order Observables are useful when dealing with nested asynchronous operations
such as making multiple HTTP requests in sequence or handling multiple events in a specific
order. They allow you to chain and combine Observables, creating more complex data
streams.

To work with higher-order Observables, RxJS provides several operators such as mergeMap,
switchMap, and concatMap. These operators help to flatten and merge the nested
Observables into a single Observable stream that can be easily subscribed to.

Overall, higher-order Observables provide a powerful tool for managing complex


asynchronous operations and can help make your code more concise and readable.
Q19. How can you use higher-order Observables in Angular applications?

A19. Higher-order Observables can be used in Angular applications to handle complex,


nested asynchronous operations. You can use various RxJS operators to transform, combine,
or flatten the higher-order Observables into a single output Observable. Some common
operators used with higher-order Observables include switchMap, mergeMap, concatMap,
and exhaustMap. Here's an example:

import { HttpClient } from '@angular/common/http'; import { switchMap } from


'rxjs/operators'; // ... constructor(private httpClient: HttpClient) {} fetchData()
{ this.httpClient.get('https://api.example.com/parent-
data').pipe( switchMap(parentData => { const childDataUrl =
parentData.childDataUrl; return
this.httpClient.get(childDataUrl); }) ).subscribe( (childData) => console.log('Child
Data:', childData), (error) => console.log('Error:', error), () => console.log('Completed')
); }

In this example, the fetchData method fetches data from an API that returns a URL for
additional child data. The switchMap operator is used to switch from the parent data
Observable to the child data Observable, effectively flattening the higher-order Observable.

Q20. What is the purpose of the switchMap() operator?

A20. The purpose of the switchMap() operator is to map each value emitted by a source
Observable to an inner Observable and switch to the latest emitted inner Observable,
canceling any previous subscriptions. It is useful when you want to switch between
Observables based on the latest emitted value and ensure that only one inner Observable is
active at any time. This helps prevent race conditions and unnecessary processing in cases
where the source Observable emits values rapidly.

For example, the switchMap() operator is commonly used in Angular applications for
handling search input, where you want to perform an HTTP request for the latest search term
while canceling any previous in-progress requests:

import { FormControl } from '@angular/forms'; import { debounceTime,


distinctUntilChanged, switchMap } from 'rxjs/operators'; // ... searchInput = new
FormControl(); ngOnInit() { this.searchInput.valueChanges.pipe( debounceTime(300),
distinctUntilChanged(), switchMap(searchTerm =>
this.performSearch(searchTerm)) ).subscribe( (searchResults) => console.log('Search
Results:', searchResults), (error) => console.log('Error:', error), () =>
console.log('Completed') ); } performSearch(searchTerm) { // Perform HTTP request
using searchTerm and return an Observable }
In this example, the switchMap() operator is used to switch between search result
Observables as the user types in a search input field, ensuring that only the latest search
request is processed.

Angular RxJS Best Practices and Performance Optimization

In this category of interview questions, candidates are evaluated based on their knowledge
of best practices and performance optimization techniques when using Angular and RxJS
together. These questions may cover topics such as memory management, error handling,
optimization of data streams, and efficient use of RxJS operators. Candidates should be able
to demonstrate their understanding of the importance of adhering to best practices and
optimizing performance in Angular applications using RxJS, as well as provide examples of
how they have applied these principles in their work.

A. Observable and Subscription Management

Q21. How can you prevent memory leaks when using Observables in Angular?

A21. To prevent memory leaks when using Observables in Angular, you need to unsubscribe
from the Observable when the component is destroyed. There are several ways to achieve
this:

1. Manual unsubscribing: You can store the subscription and unsubscribe in the
ngOnDestroy lifecycle hook.

import { Subscription } from 'rxjs'; // ... private subscription: Subscription; ngOnInit()


{ this.subscription = this.observable.subscribe(value => console.log(value)); }
ngOnDestroy() { this.subscription.unsubscribe(); }

1. Using takeUntil operator: You can use the takeUntil operator along with a Subject
that emits a value when the component is destroyed.

import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; // ... private
destroy$ = new Subject<void>(); ngOnInit()
{ this.observable.pipe( takeUntil(this.destroy$) ).subscribe(value =>
console.log(value)); } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); }

1. Using the async pipe: When using the async pipe in your templates, Angular
automatically handles the subscription and unsubscription.

<!-- In your component template --> <div>{{ observable | async }}</div>


Q22. How can you share a single Observable among multiple subscribers?

A22. You can use the share() or shareReplay() operators to share a single Observable among
multiple subscribers. The share() operator creates a multicast Observable that shares a single
subscription to the source Observable. The shareReplay() operator does the same but also
replays a specified number of emitted values to new subscribers.

import { share, shareReplay } from 'rxjs/operators'; const sharedObservable =


this.sourceObservable.pipe(share()); const sharedReplayObservable =
this.sourceObservable.pipe(shareReplay(1));

B. Error Handling and Recovery

Q23. What are some best practices for error handling in RxJS?

A23. Some best practices for error handling in RxJS include:

1. Use the catchError operator to handle errors within the Observable pipeline.
2. When handling errors, consider providing a fallback value, returning a new
Observable, or rethrowing the error.
3. Use the retry or retryWhen operators to retry failed operations.
4. Make sure to handle errors in the subscribe method's error callback as a last resort.

Q24. How can you recover from errors and continue processing in RxJS?

A24. To recover from errors and continue processing in RxJS, you can use the catchError
operator, which allows you to handle errors within the Observable pipeline and continue with
a new Observable or a fallback value.

import { catchError } from 'rxjs/operators'; this.sourceObservable.pipe( catchError(error


=> { console.error('Error:', error); return of('Fallback value'); }) ).subscribe(value =>
console.log(value));

C. Performance Optimization Techniques

Q25. How can you optimize Angular applications using RxJS?

A25. To optimize Angular applications using RxJS:

1. Use pipeable operators to reduce the size of your bundle.


2. Unsubscribe from Observables when they are no longer needed to prevent memory
leaks.
3. Use the async pipe in templates to automatically manage subscriptions.
4. Utilize operators like debounceTime, distinctUntilChanged, and throttleTime to limit
the frequency of emitted values.
5. Use share() or shareReplay() operators to share a single subscription among multiple
subscribers.

Q26. What are some performance pitfalls to avoid when using RxJS in Angular?

A 26. RxJS is a powerful library that is widely used in Angular for reactive programming.
However, it is important to be aware of some performance pitfalls that can affect the
performance of your Angular application. Here are some common performance pitfalls to
avoid when using RxJS in Angular:

1. Overusing the async pipe: While the async pipe is a convenient way to subscribe to
an observable in your template, it can lead to performance issues if you overuse it.
Each use of the async pipe creates a new subscription, which can add up if you have a
large number of components using it. To avoid this, consider subscribing to the
observable in your component instead and using the takeUntil operator to
unsubscribe when the component is destroyed.
2. Using unnecessary operators: RxJS has a large number of operators, and it can be
tempting to use them all. However, each operator adds overhead, so it's important to
use only the operators you need. Be mindful of which operators you are using and
consider whether they are really necessary.
3. Creating too many observables: Creating too many observables can also impact
performance. If you have multiple observables that emit the same data, consider
using the share operator to share the subscription and avoid creating unnecessary
observables.
4. Not using the unsubscribe method: When you subscribe to an observable, you need
to unsubscribe when you are done to avoid memory leaks. If you don't unsubscribe,
the subscription will stay active even after the component is destroyed, which can
lead to performance issues. To avoid this, always unsubscribe when you are done
with the subscription.
5. Using ngZone.run unnecessarily: The ngZone.run method is used to run code outside
of Angular's zone. While this can be useful in some cases, it can also impact
performance if used unnecessarily. Be mindful of when you are using ngZone.run and
consider whether it is really necessary.

Q: When we use the switchMap, mergeMap and concatMap?


Ans:

concatMap(), mergeMap(), switchMap() and exhaustMap(). All of these operators are


flattening operators used to flatten observables, but they are applicable in very different
scenarios. switchMap and mergeMap are probably going the be the most powerful and
frequently used operators. Its is thereby critical to understand the difference between the
two in order to spend less time debugging code.

To understand core concept of RxJS Map and different merge strategy click here

Q: What is RxJS concatMap?


Ans:

concatMap : Projects each source value to an Observable which is merged in the output
Observable, in a serialized fashion waiting for each one to complete before merging the next
- Official RxJS Docs

To understand RxJS concatMap click here

Q: What is RxJS mergeMap?


Ans:

mergeMap : mergeMap allows for multiple inner subscriptions to be active at a time.


Because of this, one of the most common use-case for mergeMap is requests that should
not be canceled.

To understand RxJS mergeMap click here

Q: What is RxJS switchMap?


Ans:

switchMap : Simply put, it means switching to a new observable. The previous inner
observable (result of the function you provided) is canceled for each emission and the new
observable is subscribed.

To understand RxJS switchMap click here

Q: What is NgRx?
Ans:

NgRx stands for Angular Reactive Extensions, NgRx Store provides reactive state
management for Angular apps inspired by Redux. NgRx has libraries for managing both global
and local state. Isolation of side effects in order to achieve a more streamlined component
architecture. Developer tooling that makes it easier for developers to construct a variety of
applications.
Refer for more questions on NgRX Interview Questions

Q: When we use zip and combineLatest and withLatestFrom?


Ans:

zip and combineLatest are functions and withLatestFrom is operator that allows to combine
a few observable sequences in a different ways, that are really helpful in real world
application.

Composing functions and operators usually accept observables as their params and also they
return observable that emits array with values produced by argument observables. This result
observable emission logic is different depending on which operator or function we use

To understand RxJS more about Zip and combineLatest and withLatestFrom, click here

Q: What is Angular?
Ans:

It's a frontend framework, which was developed to build a single page application (SPA).
Click here to understand more about Angular.
Q: How to build full stack web application?
Ans:

Angular is extremely famous for modern web application development, Spring Boot and
Angular are a strong and developer-friendly combination if you want to create the full stack
web application.

To know more about Angular Spring Boot Example click here

Q: How to implement authentication in web application?


Ans:

We can use Spring Boot JWT with Angular for token authentication in web application.

To know more about Angular Spring Boot JWT Example click here

Q: What is latest version of Angular?


Ans:

The lastest version of Angular framework is Angular 9 which is in pipeline to release in this
month.

To know more about Angular 9 features, click here

Q: What is difference between Angular and AngularJS?


Ans:

Here are few differences between Angular and AngularJS are stated as follows

 AngularJS supports the MVC design model. Angular relies on components and
directives instead.
 Angular supports a hierarchical Dependency Injection with unidirectional tree-based
change detection. AngularJS doesn’t support DI
 In AngularJS, a specific ng directive is required for the image or property and an
event. Angular, on the other hand, use () and [] for blinding an event and
accomplishing property binding, respectively
 AngularJS doesn’t have mobile support while Angular does have
 While JavaScript is the recommended language for AngularJS, TypeScript is the
recommended language for Angular
Q: What is Angular Material?
Ans:

It is a UI component library. Angular Material helps in creating attractive, consistent, and fully
functional web pages as well as web applications. It does so while following modern web
design principles, including browser portability and graceful degradation.

Q: What is AOT (Ahead-Of-Time) Compilation?


Ans:

The Angular Ahead-of-Time compiler pre-compiles application components and their


templates during the build process. Apps compiled with AOT launch faster for several
reasons.

 Templates are embedded as code within their components so there is no client-side


request for template files.
 At the end of the restore view phase of the JSF request lifecycle, Seam attempts to
restore any previous long-running conversation context. If none exists, Seam creates
a new temporary conversation context.
 Application components execute immediately, without client-side compilation
 The compiler discards unused Angular directives that a tree-shaking tool can then
exclude

Q: What's New with Angular 8 Features? Angular 8 interview Questions


Ans:

Angular 8 has been official release in May 2019, new features in Angular 8 are limited, but
there are still there are a lot of interesting things happening, we have much awaited Ivy
compiler as an opt-in feature, ng deploy is officially support by CLI and many more.

Below are the most prominent features of Angular 8:

 Differential Loading of Modern JavaScript:

It is the most important feature in terms of performance, so new apps generated by


Angular CLI to have two different bundles for legacy JavaScript(ES5) and modern
JavaScript(ES2015+). This translation has provided better the speed for modern
browsers which has ES2015 support to download small app bundles.
 Angular 8 supports TypeScript 3.4

In the newest version of Angular 8, it has updated the core dependencies which
include tools like RxJS and TypeScript to v3

 The new compiler for Angular 8 is Ivy Rendering Engine

Another much awaited feature, the new rendering engine, and Bazel, the new build
system, which make possibility to build your CLI application more quickly. An opt-in
preview of the two should be available shortly

 Angular 8 enhance supports for building Web Workers

The improvements that have been made to Angular CLI bundling to eliminates the
need to put the web workers in a separate file

 Angular 8 provides dynamic imports for lazy-loaded modules

Lazy-loaded routes now use the standard dynamic import syntax instead of a custom
string. This means that TypeScript and linters will be strict checking when modules
are missing or misspelled. lazy-loaded import that looked like this:

{ path: '/admin, loadChildren: './ admin / admin.module#AdminModule'


}

Will be looked like this:

{ path: `/ admin`, loadChildren: () => import(`./admin/


admin.module`).then(a => a.AdminModule) }

 Improvement of CLI workflow

The CLI continues to improve, and the ng build, ng test and ng run are now designed
to be expanded by third-party libraries and software. For example, with a deploy
order, AngularFire is already using these new capabilities.

 Angular 8 supports Unit Test Helpers

2 New Unit Test Helpers were introduced so that we can upgrade Angular Project to
Unit Test Angular Service

The new feature of Angular 8 has benefits, such as:


 Faster loading time
 Pre-compilation of code and rebuilding is done more faster
 Reduction in app bundle size- reduce up to 90%
 It does not affect SEO negatively
Shortly Angular 9 will be released around November 2019, and Ivy is expected to be an
Angular version 9 engine by design. Watch out for an additional feature with Angular 9.

Q: What's new in Angular 6?


Ans:

Below major new aspects introduced in Angular 6:

 RxJS 6

- Angular 6 makes use of RxJS 6 internally, RxJS released a library called rxjs-compat,
that allows you to still using one of the “old” syntaxes.

 Elements:

lets you wrap your Angular components as Web Components and embed them in a
non-Angular application

 i18n (internationalization):

Without having to build the application once per locale, any Angular application can
have “runtime i18n”

 Tree-shakeable providers:

recommended, way to register a provider, directly inside the @Injectable() decorator,


using the new providedIn attribute

 New Rendering Engine:

Ivy - increases in speed and decreases in application size.

Q: What is ViewEncapsulation and how many ways are there do to do it in Angular?


Ans:
To put simply, ViewEncapsulation determines whether the styles defined in a particular
component will affect the entire application or not. Angular supports 3 types of
ViewEncapsulation:

 Emulated : Styles used in other HTML spread to the component


 Native : Styles used in other HTML doesn’t spread to the component
 None : Styles defined in a component are visible to all components of the application

Name some rxJs Operators?

 Map - Transforms data in a observable in to a different format.


 Filter - Allows data which meets conditions.
 Merge - This operator will combine multiple Observables into one. So
if one of the observables emit a value the combined one will emit as
well.
 Concat - only when observable completes, it will start with the next
observable.
 From - This operator will turn array, promise or iterable into an
observable.
 Debouncetime - discard emitted values if a certain time didn't pass
between the last input.
 Distinctuntilchanged - only emits a value if it is different than the last
one.
 Pluck - select a property to emit.
 Delay - emits a value with a delay.

 switchMap operator will cancel any previous inner observables and switch to the new
one when a new value is emitted from the outer observable. The main idea here is to
only have one inner observable active at a time, when an inner observable is
subscribed, any previous inner observables are unsubscribed.
 concatMap operator will preserve the order of emissions, so it will wait for an inner
observable to complete before subscribing to the next one. This is useful when the
order of inner observables is important.
 mergeMap operator will subscribe to all inner observables regardless of the outer
observable's emissions. It will merge the emissions of all inner observables and emit
them to the final stream, and it allows multiple inner observables to emit values at the
same time.

 let outerObservable = of(1, 2, 3);


outerObservable.pipe(
switchMap(val => of(val, val + 1))
).subscribe(console.log)
// output: 2,3,4,5

outerObservable.pipe(
concatMap(val => of(val, val + 1))
).subscribe(console.log)
// output: 1,2,2,3,3,4

outerObservable.pipe(
mergeMap(val => of(val, val + 1))
).subscribe(console.log)
// output: 1,2,2,3,3,4

You might also like