You are on page 1of 162

Reactive Extensions for JavaScript (RxJS) is a reactive streams library that allows you to

work with asynchronous data streams. RxJS can be used both in the browser or in the
server-side using Node.js.

RxJS has some core features that help handle async implementation:
 Observable
RxJS observables allow you to publish events. Observables have two methods:
subscribe and unsubscribe. You execute an observable by subscribing to it.
Observables model a stream of events.
 Observer
An observer is an object with next(), error(), and complete() methods that is called
when there’s an interaction with the observable. They are the objects that
subscribe to observables.
 Subscription
A subscription to the observable will trigger the observable to execute.
 Operator
An operator is a function that allows us to perform certain actions on events
executed by observables.
 Subject
A subject is the same as an EventEmitter. It is an observable that multicasts
information to observers.
 Scheduler
A scheduler handles the execution of subscriptions.
The RxJS library is great for handling async tasks. It has a large collection of operators in
filtering, error handling, conditional, creation, multicasting, and more. It is supported by
JavaScript and TypeScript, and it works well with Angular.

What exactly are asynchronous data streams?


Let’s take each word separately and put it into context.
 Asynchronous, in JavaScript means we can call a function and register a callback to
be notified when results are available, so we can continue with execution and avoid the
Web Page from being unresponsive. This is used for ajax calls, DOM-events, Promises,
WebWorkers and WebSockets.
 Data, raw information in the form of JavaScript data types as: Number, String, Objects
(Arrays, Sets, Maps).
 Streams, sequences of data made available over time. As an example, opposed to
Arrays you don’t need all the information to be present in order to start using them.
Asynchronous data streams are not new. They have been around since Unix systems, and
come in different flavours and names: streams (Node.js), pipes (Unix) or async pipes
(Angular 2).
Observable sequences
In RxJS, you represent asynchronous data streams using observable sequences or also just
called observables.
Observables are very flexible and can be used using push or pull patterns.
 When using the push pattern, we subscribe to the source stream and react to new
data as soon as is made available (emitted).
 When using the pull pattern, we are using the same operations but synchronously.
This happens when using Arrays, Generators or Iterables.
Pros and cons of RxJS
Pros
RxJS is a powerful and popular tool that continues to grow. It has over 2 million
dependent repositories on GitHub and over 22 million weekly downloads from NPM.
Let’s take a look at some of the reasons why it is so popular:
 Flexibility: It can be used with other JavaScript libraries and frameworks.
 Great API: With RxJS, you’re able to simplify your workflow with asynchronous
dataflows and save time.
 Optimized: Many developers have tested and improved it.
 Extensibility: It is designed to allow new functionalities.
 Self-sufficient: RxJS doesn’t have any third-party dependencies.
 Helpful community: Members of the RxJS community help each other solve
problems and answer questions.
Cons
Like any other tool, RxJS has a few downsides. Let’s take a look at them:
 Debugging: Debugging code with observables isn’t always simple.
 Data immutability: Reactive programming works the best when combined with
functional programming.
 tslib dependency: The only dependency RxJS has is tslib. Details of internal
implementation are not always restricted, meaning that you can see some improper
usage of access modifiers.
Observables are either hot or cold
If this plain Observable has no subscribers, it will not be triggered!
The observable is said to be cold because it does not generate new values if no
subscriptions exist. To get the numeric values printed to the console, we need to subscribe
to the Observable:

obs.subscribe();

With this, we do get the numeric values printed to the console. But what happens if we add
two subscribers to this observable:
const obs = interval(1000)
.pipe(
take(5),
tap(i => console.log("obs value "+ i) )
);

obs.subscribe(value => console.log("observer 1 received " + value));

obs.subscribe(value => console.log("observer 2 received " + value));

view raw03.ts hosted with ❤ by GitHub


What's happening here is that the Observable named obs has a side-effect: its prints to the
console via the tap() operator. Then two subscribers are added to obs, each one printing
the result value to the console as well. This is the output of the console:

obs value 0
observer 1 received 0
obs value 0
observer 2 received 0

obs value 1
observer 1 received 1
obs value 1
observer 2 received 1

Looks like the side effect is being called twice! This leads to a second important property of
Observables.
Observables are not shared by default
When we create a subscriber, we are setting up a whole new separate processing chain.
The obs variable is just a definition, a blueprint of how an a functional processing chain of
operators should be set up from the source of the event up until the sink of the event, when
that sink (the observer) is attached.

Being obs just a blueprint of how to build an operation chain, what happens when we
subscribe two observers is that two separate processing chains are set up, causing the side
effect to be printed twice, once for each chain.

There are ways to define other types of Observables where the side-effect would only be
called once (see further). The important is to realize that we should keep two things in mind
at all times when dealing with observables:
 is the observable hot or cold?
 is the observable shared or not?
Observables is a new primitive type which acts as a blueprint for how we want to create
streams, subscribe to them, react to new values, and combine streams together to build
new ones.
Features of RxJS
Following is the list of essential concepts or primary features of RxJS that are used to solve
async event management:
Observable
The observable is used to represent the idea of an invokable collection of future values or
events. It can be defined as a function that creates an observer and attaches it to the
source where values are expected. The observable examples are clicks, mouse events
from a dom element or an Http request, etc.
Observer
It is a collection of callbacks that are used to specify how to listen to values delivered by the
Observable. It can be specified as an object with next(), error() and complete() methods,
that will be executed when you have to interact with observable.
Subscription
It is used to represent the execution of an Observable. It is primarily used to cancel the
execution. For example, when the observable is created, you have to subscribe to it to
execute the observable. It can also be used to cancel the execution.
Operators
Operators are simple functions used to enable a functional programming style to deal with
collections with operations like map, filter, concat, flatMap, etc. It takes observable as input
and gives the output also in the form of observable.
Subject
A subject is equivalent to an EventEmitter and used to multicast a value or event to multiple
Observers. For example: Consider a button with an event listener; the function attached to
the event will be called whenever the user will click on the button.
Schedulers
The Schedulers are centralized dispatchers that are used to control concurrency. They are
used to control the execution when the subscription has to start and notified.

RxJS Operators
Operators are the important part of RxJS. RxJS provides a huge collection of operators.
There are over a 100+ operators in RxJS that you can use with observables. An operator is
a pure function that takes a observable as an input and provide the output in also in the
form of an observable.
In simple words, we can say that operators are simply methods that can be used with
Observables or Subjects of RxJS. RxJS operators facilitate us to change the original
observable in some manner and return a new observable. The operators do not change the
existing observable. They simply modify it and return a new one. Operators are known as
the type of functions that do not modify the variables outside of its scope. There are mainly
two types of RxJS operators:
Static Operators: The static operators are generally used to create observables. These
types of operators can be found mainly under the creation operators.
Instance Operators: The instance operators are methods on observable instances. These
are used to account the majority of RxJS operators that we have used.
Backward Skip 10sPlay VideoForward Skip 10s
How to work with Operator?
As we know that operators are pure functions which take in observable as the input and the
provided output is also an observable.
We need a pipe() method to work with operators. Let's see an example of pipe() function.
Syntax of using pipe() Method
1. let obs = of(1,2,3); // an observable
2. obs.pipe(
3. operator1(),
4. operator2(),
5. operator3(),
6. )
In the above syntax, we have created a observable using of() method. This method takes in
values 1, 2 and 3. On this observable, you can perform many operations using different
types of operators using pipe() method as the above syntax.
Let's see a working example of operators to understand the concept clearly. In this
example, we are using a filter operator to filter the even numbers and then we will use a
reduce() operator that will add all the even values and give the result.
Example 1:
1. import { of } from 'rxjs';
2. import { map, reduce, filter } from 'rxjs/operators';
3. let test1 = of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
4. let case1 = test1.pipe(
5. filter(x => x % 2 === 0),
6. reduce((acc, one) => acc + one, 0)
7. )
8. case1.subscribe(x => console.log(x));
After the execution of the program by using the node -r esm testrx.js command, we will
see the following result.
Output:

You can see that 110 is the total of all the even values of the above numbers.
Example2:
Let's see another example of interval operator. This operator will create an Observable
every time for the given time interval. In the following example, the program will return an
observable after every 1000 millisecond.
1. import { interval } from 'rxjs';
2. import { take } from 'rxjs/operators';
3. let test = interval(1000);
4. let case1 = test.pipe(take(10));
5. case1.subscribe(x => console.log(x));
Output:

Categorization of RxJS Operators


According to the official documentation for categories of RxJS operators, you can find the
following categories of operators:
oCreation
o Mathematical
o Join or Combination
o Transformation
o Filtering
o Utility
o Conditional
o Multicasting
o Error handling
o Boolean
o Aggregate
Creation Operators
Following is the list of operators that can be used as creation operators:

Index Operators Description

1. ajax The ajax operator is used to make an ajax request for the given
URL.

2. from The from operator is used to create an observable from an array,


an array-like object, a promise, an iterable object, or an
observable-like object.

3. fromEvent The fromEvent operator is used to give output as an observable


that is to be used on elements that emit an event for example
buttons, clicks, etc.

4. fromEventPattern The fromEventPattern operator is used to create an observable


from the input function that is used to register event handlers.

5. interval The interval operator is used to create an Observable for every


time for the given time interval.

6. of The of operator is used to take in the arguments passed and


convert them to observable.

7. range The range operator is used to create an Observable that gives you
a sequence of numbers based on the range provided.

8. throwError The throwError operator is used to create an observable that


notifies an error.

9. timer The timer operator is used to create an observable that emits the
value after the timeout and the value will keep increasing after
each call.

10. iif The iif operator is used to decide which Observable will be
subscribed.
Mathematical Operators
Following is the list of operators that can be used as mathematical operators:
Index Operators Description

1. count The count operator is used to take an observable with values and
convert it into an observable that gives a single value.

2. max The max method is used to take an observable with all values and
return an observable with the maximum value from the list.

3. min The min method is used to take an observable with all values and
return an observable with the minimum value from the list.

4. reduce In reduce operator, an accumulator function is used on the input


observable. It returns the accumulated value in an observable form,
with an optional seed value passed to the accumulator function.
So, the reduce function takes two arguments, one accumulator
function, and second the seed value.
Join Operators
Following is the list of operators that can be used as join operators:

Index Operators Description

1. concat The concat operator is used to sequentially emit the Observable given
as input and proceed to the next one.

2. forkJoin The forkJoin operator is used to take in an array or dict object as an


input and wait for the observable to complete and return the last values
emitted from the given observable.

3. merge The merge operator is used to take in the input observable and emit all
the values from the observable and emit one single output observable.

4. race The race operator is used to return an observable that will be a mirror
copy of the first source observable.
Transformation Operators
Following is the list of operators that can be used as transformation operators:

Index Operators Description

1. buffer The buffer operator is used to be operated on an observable and take


in argument as an observable. It starts buffering the values emitted on
its original observable array and emits when the observable taken as
an argument, emits. Once the observable taken as arguments emits,
the buffer is reset and starts buffering again on original till the input
observable emits, and the same process repeats itself.

2. bufferCount The buffercount operator is used to collect the values from the
observable on which it is called and emit the same when the buffer size
is given to buffercount matches.
3. bufferTime The bufferTime operator is similar to bufferCount. It is used to collect
the values from the observable on which it is called and emit the
bufferTimeSpan. It takes in 1 argument, i.e., bufferTimeSpan.

4. bufferToggle The bufferToggle operator is used to take two arguments, openings


and closingSelector. The opening arguments are subscribable or a
promise to start the buffer. The second argument closingSelector is
again subscribable or promises an indicator to close the buffer and
emit the values collected.

5. bufferWhen The bufferWhen operator is used to give the values in the array form, it
takes in one argument as a function that will decide when to close, emit
and reset the buffer.

6. expand The expand operator is used to take in a function as an argument


applied on the source observable recursively and on the output
observable. The final value is observable.

7. groupBy Te groupBy operator is used to group the output according to specific


conditions, and these group items are emitted as GroupedObservable.

8. map In the map operator's case, a project function is applied on each value
on the source Observable, and the same output is emitted as an
Observable.

9. mapTo In the mapTo operator, a constant value is given as output along with
the Observable every time the source Observable emits a value.

10. mergeMap In the mergeMap operator, a project function is applied on each source
value, and the output of it is merged with the output Observable.

11. switchMap The switchMap operator is used to apply a project function on each
source value. The output of it is merged with the output Observable,
and the value given is the most recent projected Observable.

12. window The window operator is used to take an argument windowboundaries


which is an observable and give back a nested observable whenever
the given windowboundaries emits.
Filtering Operators
Following is the list of operators that can be used as filtering operators:

Index Operators Description

1. debounce In the debounce operator, a value is emitted from the source


Observable after a while, and the emission is determined by another
input given as Observable or promise.

2. debounceTime The debounceTime operator is used to emit value from the source
observable only after the time is complete.
3. distinct This operator is used to give all the values from the source
observable that are distinct compared with the previous values.

4. elementAt This operator is used to give a single value from the source
observable based upon the given index.

5. filter This operator is used to filter the values from source Observable
based on the predicate function given.

6. first The first operator is used to give the first value emitted by the source
Observable.

7. last The last operator is used to give the last value emitted by the source
Observable.

8. ignoreElements The ignoreElements operator is used to ignore all the values from
the source Observable and only execute calls to complete or error
callback functions.

9. sample The sample operator is used to give the most recent value from the
source Observable, and the output will depend upon the argument
passed to it emits.

10. skip The skip operator is used to give back an observable that will skip
the first occurrence of count items taken as input.

11. throttle The throttle operator is used to give output and ignore values from
the source observable for the time determined by the input function
taken as an argument, and the same process will be repeated.
Utility Operators
Following is the list of operators that can be used as utility operators:

Index Operators Description

1. tap The tap operator contains the output, same as the source observable,
and it can be used to log the values to the user from the observable.

2. delay The delay operator is used to delay the values emitted from the source
observable based on the timeout given.

3. delayWhen The delayWhen operator is used to delay the values emitted from the
source observable based on the timeout from another observable
taken as input.

4. observeOn The observeOn operator is based on the input scheduler. It is used to


reemit the notifications from the source observable.

5. subscribeOn The subscribeOn operator helps to asynchronous subscribes to the


source observable based on the scheduler taken as input.
6. timeInterval The timeInterval operator is used to return an object containing current
value, and the time elapsed between the current and previous value
calculated using the scheduler input.

7. timestamp The timestamp operator is used to return the timestamp along with the
value emitted from the source observable. It tells about the time when
the value was emitted.

8. timeout The timeout operator is used to throw an error if the source observable
does not emit a value after the given timeout.

9. toArray The toArray operator is used to accumulate all the source values from
the observable and provide their outputs as an array when the source
completes.
Conditional Operators
Following is the list of operators that can be used as conditional operators:

Index Operators Description

1. defaultIfEmpty The defaultIfEmpty operator is used to return a default value if the


source observable is empty.

2. every The every operator is used to return an observable based on the input
function, which satisfies the condition on each of the values on source
observable.

3. find The find operator is used to return the observable when the source
observable's first value satisfies the condition for the predicate
function taken as input.

4. findIndex The findIndex operator is based on the input schedule. It is used to


reemit the notifications from the source observable.

5. isEmpty The isEmpty operator gives the output "True" if the input observable
goes for complete callback without emitting any values and "False" if
the input observable emits any values.
Multicasting Operators
Following is the list of operators that can be used as multicasting operators:

Index Operators Description

1. multicast A multicast operator shares the single subscription created with


other subscribers. The params that multicast takes in is a subject or
a factory method that returns a ConnectableObservable that has a
connect method. The connect method is called to subscribe.

2. publish The publish operator is used to give back ConnectableObservable


and use connect method to subscribe to the observables.
3. publishBehavior The publishBehaviour makes use of BehaviourSubject, and returns
ConnectableObservable. The connect method is used to subscribe
to the observable created.

4. publishLast The publishBehaviour operator makes use of AsyncSubject, and


returns ConnectableObservable. The connect method is used to
subscribe to the observable created.

5. publishReplay The publishReplay operator uses behavior subject where it can


buffer the values, replay the same to the new subscribers, and
return ConnectableObservable. The connect method is used to
subscribe to the observable created.

6. share The share operator is an alias for a multicast operator. The only
difference is that you don't have to called the connect method
manually to start the subscription.
Error Handling Operators
Following is the list of operators that can be used as error handling operators:

Index Operators Description

1. catchError The catchError operator is used to take care of catching errors on


the source observable by returning a new observable or an error.

2. retry The retry operator is used to take care of retrying back on the
source observable if there is an error. The retry is done according to
the given input count.

3. retryWhen -

RxJS Observables
In RxJS, an observable is a function that is used to create an observer and attach it to the
source where values are expected from. For example, clicks, mouse events from a DOM
element or an Http request, etc. are the example of observable.
In other words, you can say that observer is an object with callback functions, which is
called when there is interaction to the Observable. For example, the source has interacted
for an example, button click, Http request, etc.
Observables can also be defined as lazy Push collections of multiple values. Let's see a
simple example to understand how observables are used to push the values.
See the following example:
Backward Skip 10sPlay VideoForward Skip 10s
1. import { Observable } from 'rxjs';
2. const observable = new Observable(subscriber => {
3. subscriber.next(10);
4. subscriber.next(20);
5. subscriber.next(30);
6. setTimeout(() => {
7. subscriber.next(40);
8. subscriber.complete();
9. }, 1000);
10. });
In the above example, there is an observable that pushes the values 10, 20, 30 immediately
and synchronously when subscribed, but the value 40 will be pushed after one second
since the subscribe method has called.
If you want to invoke the observable and see the above values, you have to subscribe to it.
See the following example:
1. import { Observable } from 'rxjs';
2. const observable = new Observable(subscriber => {
3. subscriber.next(10);
4. subscriber.next(20);
5. subscriber.next(30);
6. setTimeout(() => {
7. subscriber.next(40);
8. subscriber.complete();
9. }, 1000);
10. });
11.
12. console.log('These are the values just before subscribe');
13. observable.subscribe({
14. next(x) { console.log('We have got value ' + x); },
15. error(err) { console.error('something wrong occurred: ' + err); },
16. complete() { console.log('Done successfully'); }
17. });
18. console.log('This value is just after subscribe');
Output:
When we execute the above program, we shall the following result on the console:

Observables are generalizations of functions


We know that observables are functions that act as clicks, mouse events from a DOM
element or an Http request, etc. but observables are not like EventEmitters, nor are they
like Promises for multiple values. In some cases, observables may act like EventEmitters,
namely when they are multicasted using RxJS Subjects, but usually, they don't act like
EventEmitters.
Observables are like functions with zero arguments, but generalize those to allow multiple
values.
Let's see an example to understand this clearly.
A simple example of a function:
1. function foo() {
2. console.log('Hello World!');
3. return 123;
4. }
5. const x = foo.call(); // same as foo()
6. console.log(x);
7. const y = foo.call(); // same as foo()
8. console.log(y);
Output:
You will see the following output:
"Hello World!"
123
"Hello World!"
123
Let's write the same example, but with Observables:
1. import { Observable } from 'rxjs';
2. const foo = new Observable(subscriber => {
3. console.log('Hello World!');
4. subscriber.next(123);
5. });
6. foo.subscribe(x => {
7. console.log(x);
8. });
9. foo.subscribe(y => {
10. console.log(y);
11. });
Output:
You will see the same output as above:

You can see this because both functions and Observables are lazy computations. If you
don't call the function, the console.log('Hello World!') won't happen. Also, with Observables,
if you don't "call" it with subscribe, the console.log('Hello World!') won't happen.
Working of an Observable
There are three phases in an observable:
o Creating Observables
o Subscribing to Observables
o Executing Observables
Creating Observables
There are two ways to create observables:
o Using the Observable constructor method
o Using Observable create() method
Using the Observable constructor method
Let's create an observable using the observable constructor method and add a message,
"This is my first Observable" using subscriber.next method available inside Observable.
testrx.js file:
1. import { Observable } from 'rxjs';
2. var observable = new Observable(
3. function subscribe(subscriber) {
4. subscriber.next("This is my first Observable")
5. }
6. );
You can also create Observable using, Observable.create() method as follows:
1. import { Observable } from 'rxjs';
2. var observer = Observable.create(
3. function subscribe(subscriber) {
4. subscriber.next("This is my first Observable")
5. }
6. );
Subscribing to Observables
Subscribing to an observable is like calling a function. It provides callbacks where the data
will be delivered to.
You can subscribe to an observable by using the following syntax:
Syntax:
1. observable.subscribe(x => console.log(x));
See the above example with subscribe:
testrx.js file:
1. import { Observable } from 'rxjs';
2. var observer = new Observable(
3. function subscribe(subscriber) {
4. subscriber.next("This is my first Observable")
5. }
6. );
7. observer.subscribe(x => console.log(x));
Output:

Executing Observables
An observable is executed when it is subscribed. There are generally three methods in an
observer that are notified:
next(): This method is used to send values like a number, string, object etc.
complete(): This method doesn't send any value. It indicates that the observable is
completed.
error(): This method is used to notify the error if any.
Let's see an example where we have created the observable with all three notifications and
execute that example:
testrx.js file:
1. import { Observable } from 'rxjs';
2. var observer = new Observable(
3. function subscribe(subscriber) {
4. try {
5. subscriber.next("This is my first Observable");
6. subscriber.next("Testing Observable");
7. subscriber.complete();
8. } catch(e){
9. subscriber.error(e);
10. }
11. }
12. );
13. observer.subscribe(x => console.log(x), (e)=>console.log(e),
14. ()=>console.log("Observable is completed now."));
The error method is invoked only if there is an error. When you run the above code, you will
see the following output in the console.
Output:

RxJS Observables
In RxJS, an observable is a function that is used to create an observer and attach it to the
source where values are expected from. For example, clicks, mouse events from a DOM
element or an Http request, etc. are the example of observable.
In other words, you can say that observer is an object with callback functions, which is
called when there is interaction to the Observable. For example, the source has interacted
for an example, button click, Http request, etc.
Observables can also be defined as lazy Push collections of multiple values. Let's see a
simple example to understand how observables are used to push the values.
See the following example:
Backward Skip 10sPlay VideoForward Skip 10s
1. import { Observable } from 'rxjs';
2. const observable = new Observable(subscriber => {
3. subscriber.next(10);
4. subscriber.next(20);
5. subscriber.next(30);
6. setTimeout(() => {
7. subscriber.next(40);
8. subscriber.complete();
9. }, 1000);
10. });
In the above example, there is an observable that pushes the values 10, 20, 30 immediately
and synchronously when subscribed, but the value 40 will be pushed after one second
since the subscribe method has called.
If you want to invoke the observable and see the above values, you have to subscribe to it.
See the following example:
1. import { Observable } from 'rxjs';
2. const observable = new Observable(subscriber => {
3. subscriber.next(10);
4. subscriber.next(20);
5. subscriber.next(30);
6. setTimeout(() => {
7. subscriber.next(40);
8. subscriber.complete();
9. }, 1000);
10. });
11.
12. console.log('These are the values just before subscribe');
13. observable.subscribe({
14. next(x) { console.log('We have got value ' + x); },
15. error(err) { console.error('something wrong occurred: ' + err); },
16. complete() { console.log('Done successfully'); }
17. });
18. console.log('This value is just after subscribe');
Output:
When we execute the above program, we shall the following result on the console:

Observables are generalizations of functions


We know that observables are functions that act as clicks, mouse events from a DOM
element or an Http request, etc. but observables are not like EventEmitters, nor are they
like Promises for multiple values. In some cases, observables may act like EventEmitters,
namely when they are multicasted using RxJS Subjects, but usually, they don't act like
EventEmitters.
Observables are like functions with zero arguments, but generalize those to allow multiple
values.
Let's see an example to understand this clearly.
A simple example of a function:
1. function foo() {
2. console.log('Hello World!');
3. return 123;
4. }
5. const x = foo.call(); // same as foo()
6. console.log(x);
7. const y = foo.call(); // same as foo()
8. console.log(y);
Output:
You will see the following output:
"Hello World!"
123
"Hello World!"
123
Let's write the same example, but with Observables:
1. import { Observable } from 'rxjs';
2. const foo = new Observable(subscriber => {
3. console.log('Hello World!');
4. subscriber.next(123);
5. });
6. foo.subscribe(x => {
7. console.log(x);
8. });
9. foo.subscribe(y => {
10. console.log(y);
11. });
Output:
You will see the same output as above:

You can see this because both functions and Observables are lazy computations. If you
don't call the function, the console.log('Hello World!') won't happen. Also, with Observables,
if you don't "call" it with subscribe, the console.log('Hello World!') won't happen.
Working of an Observable
There are three phases in an observable:
o Creating Observables
o Subscribing to Observables
o Executing Observables
Creating Observables
There are two ways to create observables:
o Using the Observable constructor method
o Using Observable create() method
Using the Observable constructor method
Let's create an observable using the observable constructor method and add a message,
"This is my first Observable" using subscriber.next method available inside Observable.
testrx.js file:
1. import { Observable } from 'rxjs';
2. var observable = new Observable(
3. function subscribe(subscriber) {
4. subscriber.next("This is my first Observable")
5. }
6. );
You can also create Observable using, Observable.create() method as follows:
1. import { Observable } from 'rxjs';
2. var observer = Observable.create(
3. function subscribe(subscriber) {
4. subscriber.next("This is my first Observable")
5. }
6. );
Subscribing to Observables
Subscribing to an observable is like calling a function. It provides callbacks where the data
will be delivered to.
You can subscribe to an observable by using the following syntax:
Syntax:
1. observable.subscribe(x => console.log(x));
See the above example with subscribe:
testrx.js file:
1. import { Observable } from 'rxjs';
2. var observer = new Observable(
3. function subscribe(subscriber) {
4. subscriber.next("This is my first Observable")
5. }
6. );
7. observer.subscribe(x => console.log(x));
Output:
Executing Observables
An observable is executed when it is subscribed. There are generally three methods in an
observer that are notified:
next(): This method is used to send values like a number, string, object etc.
complete(): This method doesn't send any value. It indicates that the observable is
completed.
error(): This method is used to notify the error if any.
Let's see an example where we have created the observable with all three notifications and
execute that example:
testrx.js file:
1. import { Observable } from 'rxjs';
2. var observer = new Observable(
3. function subscribe(subscriber) {
4. try {
5. subscriber.next("This is my first Observable");
6. subscriber.next("Testing Observable");
7. subscriber.complete();
8. } catch(e){
9. subscriber.error(e);
10. }
11. }
12. );
13. observer.subscribe(x => console.log(x), (e)=>console.log(e),
14. ()=>console.log("Observable is completed now."));
The error method is invoked only if there is an error. When you run the above code, you will
see the following output in the console.
Output:

RxJS Subjects
An RxJS Subject is like an Observable. It is a special type of Observable that allows values
to be multicasted to many Observers. In simple words, we can say that an RxJS subject is
an Observable can multicast or talk to many observers.
According to its official definition, "A Subject is like an Observable, but can multicast to
many Observers. Subjects are like EventEmitters: they maintain a registry of many
listeners."
An RxJS subject can be subscribed to, just like we usually do with Observables. It also has
methods such as next(), error() and complete(), which we have already seen and used in
our Observable creation function.
Difference between RxJS Observable and RxJS Subject
Every Subject is an Observable. We can subscribe to a given Subject just like an
observable, and it will start receiving values usually. From the perspective of the Observer,
it cannot be decided whether the Observable execution is coming from a plain unicast
Observable or a Subject.
The main difference between an Observable and a Subject is that a plain Observable by
default is unicast. It means that each subscribed Observer owns an independent execution
of the Observable. On the other hand, Subjects are multicast. A Subject is like an
Observable, but it can multicast to many Observers. The main reason behind using
Subjects is to multicast.
See an example of Observable:
Example 1
1. import * as Rx from "rxjs";
2. const observable = Rx.Observable.create((observer) => {
3. observer.next(Math.random());
4. });
5. // subscription 1
6. observable.subscribe((data) => {
7. console.log(data);
8. });
9. // subscription 2
10. observable.subscribe((data) => {
11. console.log(data);
12. });
After executing the above example, we will see the following result. Here, you will see that
Observables are unicast by design so, they will produce different random results every time
you execute the above example. See the following output:
Output:

Here, you can see that result is different for both subscriptions every time we execute the
program. This isn't very pleasant if you expect that each subscriber receives the same
values. Subjects are used to overcome this issue because subjects can multicast. It means
that one Observable execution is shared among multiple subscribers.
Subjects are like EventEmitters. They are used to maintain a registry of many listeners, so
when we call subscribe on a Subject, it does not invoke a new execution. It simply registers
the given Observer in a list of Observers.
Using RxJS Subjects
Let's see how to use Subjects to multicast and to overcome the above issue.
Example 2
1. import * as Rx from "rxjs";
2. const subject = new Rx.Subject();
3. // subscriber 1
4. subject.subscribe((data) => {
5. console.log(data);
6. });
7. // subscriber 2
8. subject.subscribe((data) => {
9. console.log(data);
10. });
11. subject.next(Math.random());
Output:
After executing the above example, we will see the following result.

Here, you can see that every time we execute the program, it shows the different random
numbers, but the values for both subscriptions are the same. It means the two subscriptions
are getting the same data.
How to Convert Observables from Unicast to Multicast
The RxJS Observables are solely data producers, but the RxJS Subjects can be used as a
data producer as well as a data consumer. By using Subjects as a data consumer, we can
use them to convert Observables from unicast to multicast. See the following example:
Example 3
1. import * as Rx from "rxjs";
2. const observable = Rx.Observable.create((observer) => {
3. observer.next(Math.random());
4. });
5. const subject = new Rx.Subject();
6. // subscriber 1
7. subject.subscribe((data) => {
8. console.log(data);
9. });
10. // subscriber 2
11. subject.subscribe((data) => {
12. console.log(data);
13. });
14. observable.subscribe(subject);
Output:
After executing the above example, we will see the following result.

Here, we have passed our Subject to the subscribe function. It took the Observable's
values, and then all the subscribers to that Subject immediately receive that value.
How to create an RxJS Subject?
Let's see how to work with RxJS subjects. To work with an RxJS subject, we need to import
Subject in the following manner:
1. import { Subject } from 'rxjs';
Now, use the following method to create a subject object:
1. const subject_test = new Subject();
Same as the RxJS Observables, an RxJS Subject also has the following three methods:
o next(v)
o error(e)
o complete()
How to subscribe to the RxJS Subject?
After creating the RxJS subject, we have to subscribe to it. A Subscription is an object that
is used to represent a disposable resource, usually the execution of the Subject. We can
easily create multiple subscriptions on the Subject by using the following method:
1. subject_test.subscribe({
2. next: (v) => console.log(`From Subject : ${v}`)
3. });
4. subject_test.subscribe({
5. next: (v) => console.log(`From Subject: ${v}`)
6. });
How to pass data to Subject?
After subscription, we need to pass data to the subject we have created. We can do this by
using the next() method.
1. subject_test.next("A");
This data will be passed to all the subscription added on the subject.
Let's see a complete example of RxJS Subject. Here, we will use above three methods:
next(v), error(e), and complete()
Example using next(v) method:
1. import { Subject } from 'rxjs';
2. const subject_test = new Subject();
3. subject_test.subscribe({
4. next: (v) => console.log(`From Subject : ${v}`)
5. });
6. subject_test.subscribe({
7. next: (v) => console.log(`From Subject: ${v}`)
8. });
9. subject_test.next("Hello");
10. subject_test.next("Good Morning");
Here, we have created an object named "subject_test" by calling a new Subject(). After
that, the subject_test object has reference to next() method.
Output:

Example using complete() method:


We can use the complete() method to stop the subject execution. See the following
example:
1. import { Subject } from 'rxjs';
2. const subject_test = new Subject();
3. subject_test.subscribe({
4. next: (v) => console.log(`From Subject : ${v}`)
5. });
6. subject_test.subscribe({
7. next: (v) => console.log(`From Subject: ${v}`)
8. });
9. subject_test.next("Hello");
10. subject_test.complete();
11. subject_test.next("Good Morning");
Output:
Example using error() method:
Let's see how to call error () method.
1. import { Subject } from 'rxjs';
2. const subject_test = new Subject();
3. subject_test.subscribe({
4. error: (e) => console.log(`From Subject : ${e}`)
5. });
6. subject_test.subscribe({
7. error: (e) => console.log(`From Subject : ${e}`)
8. });
9. subject_test.error(new Error("There is an error message"));
Output:

Types of RxJS Subjects


There are mainly four variants of RxJS subjects:
1. Subject - This is the standard RxJS Subject. It doesn't have any initial value or
replay behaviour.
2. BehaviorSubject - This variant of RxJS subject requires an initial value and emits its
current value (last emitted item) to new subscribers.
3. ReplaySubject - This variant of RxJS subject is used to emit a specified number of
last emitted values (a replay) to new subscribers.
4. AsyncSubject - The AsyncSubject emits the latest value to observers upon
completion.
BehaviorSubject
The BehaviorSubject is used to denote "the current and latest value when called". It stores
the latest value emitted to its consumers, and whenever a new Observer subscribes, it will
immediately receive the "current value" from the BehaviorSubject.
BehaviorSubjects are mainly used to represent "values over time". For example, an event
stream of birthdays is a Subject, but the stream of a person's age would be a
BehaviorSubject.
Syntax:
1. import { BehaviorSubject } from 'rxjs';
2. const subject = new BehaviorSubject("given_value");
3. // initialized the behaviour subject with value: given_value
Example
1. import { BehaviorSubject } from 'rxjs';
2. const subject = new BehaviorSubject(0); // 0 is the initial value
3. subject.subscribe({
4. next: (v) => console.log(`observerA: ${v}`)
5. });
6. subject.next(1);
7. subject.next(2);
8. subject.subscribe({
9. next: (v) => console.log(`observerB: ${v}`)
10. });
11. subject.next(3);
Output:

ReplaySubject
A ReplaySubject is pretty similar to a BehaviorSubject. It is also used to send old values to
new subscribers, but it can also record a part of the Observable execution. A ReplaySubject
records multiple values from the Observable execution and replays them to new
subscribers.
Syntax:
1. import { ReplaySubject } from 'rxjs';
2. const replay_subject = new ReplaySubject(given_value);
While creating a ReplaySubject, you can specify how many values you have to replay. See
the following example:
Example
1. import { ReplaySubject } from 'rxjs';
2. const subject = new ReplaySubject(3); // buffer 3 values for new subscribers
3. subject.subscribe({
4. next: (v) => console.log(`observerA: ${v}`)
5. });
6. subject.next(1);
7. subject.next(2);
8. subject.next(3);
9. subject.next(4);
10. subject.subscribe({
11. next: (v) => console.log(`observerB: ${v}`)
12. });
13. subject.next(5);
Output:

How to set a Window time?


You can also specify a window time in milliseconds, besides of the buffer size, to determine
how old the recorded values can be.
See the following example where we have used a large buffer size of 100, but a window
time parameter of just 500 milliseconds.
Example
1. import { ReplaySubject } from 'rxjs';
2. const subject = new ReplaySubject(100, 500 /* windowTime */);
3. subject.subscribe({
4. next: (v) => console.log(`observerA: ${v}`)
5. });
6. let i = 1;
7. setInterval(() => subject.next(i++), 200);
8. setTimeout(() => {
9. subject.subscribe({
10. next: (v) => console.log(`observerB: ${v}`)
11. });
12. }, 1000);
Output:
observerA: 1
observerA: 2
observerA: 3
observerA: 4
observerB: 3
observerB: 4
observerA: 5
observerB: 5
observerA: 6
observerB: 6
//..... and so on.

AsyncSubject
In this variant of RxJS Subject, only the last value of the Observable execution is sent to its
observers and is also done after the complete() method is called.
Syntax:
1. import { AsyncSubject } from 'rxjs';
2. const async_subject = new AsyncSubject();
Example
1. import { AsyncSubject } from 'rxjs';
2. const subject = new AsyncSubject();
3. subject.subscribe({
4. next: (v) => console.log(`observerA: ${v}`)
5. });
6. subject.next(1);
7. subject.next(2);
8. subject.next(3);
9. subject.next(4);
10. subject.subscribe({
11. next: (v) => console.log(`observerB: ${v}`)
12. });
13. subject.next(5);
14. subject.complete();
Output:
RxJS Working with Scheduler
What is an RxJS Scheduler?
An RxJS Scheduler is a way to control the timing strategy used to execute tasks in RxJS
apps or reactive applications. A scheduler comes in action to control when a subscription
starts and when notifications are delivered.
According to the official documentation of RxJS application website, a Scheduler is defined
as "A Scheduler is an entity that facilitates you to define in what execution context, an
Observable will deliver notifications to its Observer."
An RxJS Scheduler consists of the following three components:
1. Data structure: An RXJS Scheduler is a data structure. It knows how to store and
queue tasks according to their priority or other criteria.
2. Execution context: An RxJS Scheduler is an execution context. It is used to denote
where and when the task is executed (For example: immediately, or in another
callback mechanism such as setTimeout or process.nextTick, or the animation
frame).
3. Virtual clock: An RxJS Scheduler consists of a virtual clock that provides a notion of
"time" by a getter method now() on the Scheduler. Tasks being scheduled on a
particular scheduler will adhere only to the time denoted by that clock.
How to Define RxJS Scheduler?
We know that an RxJS Scheduler controls the execution of the program when the
subscription has to start. We can define a basic scheduler in the following way.
Syntax:
1. import { of, asyncScheduler } from "rxjs";
2. import { observeOn } from "rxjs/operators";
3. of(1, 2, 3)
4. .pipe(observeOn(asyncScheduler))
5. .subscribe(val => console.log(val));
Let's see synchronous Observable and asynchronous Observable both and notice the
difference by comparing the output of both:
See the synchronous example
Example 1
1. import { of, asyncScheduler } from "rxjs";
2. import { observeOn } from "rxjs/operators";
3. const observable = of(1, 2, 3);
4. console.log("Before sync subscribe");
5. observable.subscribe({
6. next(x) {
7. console.log(`Got sync value ${x}`);
8. },
9. error(err) {
10. console.error(`Something wrong occurred: ${err}`);
11. },
12. complete() {
13. console.log("This is done now.");
14. }
15. });
16. console.log("After sync subscribe");
Output:
After the execution of the above program, you will see the following result:

See the asynchronous example (By using Scheduler)


Example 2
1. import { of, asyncScheduler } from "rxjs";
2. import { observeOn } from "rxjs/operators";
3. const observable = of(1, 2, 3);
4. console.log("Before async subscribe");
5. observable.pipe(observeOn(asyncScheduler)).subscribe({
6. next(x) {
7. console.log(`Got async value ${x}`);
8. },
9. error(err) {
10. console.error(`Gomething wrong occurred: ${err}`);
11. },
12. complete() {
13. console.log("This is done now.");
14. }
15. });
16. console.log("After async subscribe");
Output:
After the execution of the above program, you will see the following result:
Example explanation
o You can see in the above examples, the asyncScheduler defers the execution of
the Observable until after the synchronous code is run.
o The async Scheduler operates with a setTimeout or setInterval. Even if the delay is
zero, it still runs on setTimeout or setInterval. It will ll run in the next event loop
iteration.
o The asyncScheduler consists of a schedule() method that takes a delay argument,
which refers to the quantity of time according to the Scheduler's own internal clock.
The internal clock doesn't have anything to do with the actual clock time. Temporal
operations are dictated by the Scheduler's clock, not the real clock.
o This can be very useful in testing since we can easily set a time for testing while the
tasks are run asynchronously.
Type of RxJS Schedulers
RxJS provides different schedulers that can be created and returned by using static
properties of the Scheduler object. Let's see the different Schedulers and also explain the
differences between them.
An RxJS Scheduler can be categorized in the following Scheduler types:

Index Scheduler Type Purpose of Scheduler Type

1. Null By using the null scheduler type, the notifications are


delivered synchronously and recursively. This is useful
for constant time or tail-recursive operations.

2. queueScheduler The queueScheduler type of Scheduler is used to


schedule on a queue in the current event frame. It is very
useful for iteration.

3. asapScheduler The asapScheduler is a scheduler type used to schedule


on the microtask queue, which is the same one used for
promises.

4. asyncScheduler The asyncScheduler type is used for time-based


operations. The works of this scheduler type are
scheduled with setInterval.
5. animationFrameScheduler The animationFrameScheduler type of Scheduler is used
to schedule tasks to run just before the next browser
content repaint. It can be used to smooth browser
animations.
Using Schedulers
We have already used schedulers in our RxJS code without explicitly stating the type of
schedulers that we used. We don't find the requirement of specifying the type of the
Scheduler because all Observable operators that deal with concurrency have optional
schedulers. If we do not provide the Scheduler, RxJS will automatically choose a default
scheduler using the least concurrency principle.
For example:
o If we use operators that return an observable with a finite and small number of
messages, RxJS uses no Scheduler that would be null or undefined.
o If we use operators that return a potentially large or infinite number of messages,
RxJS will automatically use queue Scheduler.
o If we use operators that use timers, the RxJS will use async.
By default, RxJS uses the least concurrency scheduler. To introduce concurrency for
performance purposes, we can pick a different scheduler accordingly. To specify a
particular scheduler, we can use those operator methods that take a scheduler, e.g.,
from([10, 20, 30], asyncScheduler).
Static creation operators usually take a Scheduler as an argument. For instance,
from(array, scheduler) lets you specify the Scheduler to use when delivering each
notification converted from the array. It is usually the last argument to the operator.
Following is a list of static creation operators that takes a Scheduler argument:
o bindCallback
o bindNodeCallback
o combineLatest
o concat
o empty
o from
o fromPromise
o interval
o merge
o of
o range
o throw
o timer
Some operators also take a time related Scheduler arguments such as bufferTime,
debounceTime, delay, auditTime, sampleTime, throttleTime, timeInterval, timeout,
timeoutWith, windowTime etc.
Other instance operators like cache, combineLatest, concat, expand, merge,
publishReplay, startWith also take a Scheduler argument.
With Schedulers, we can control when data are emitted by Observables. There're different
kinds of Schedulers which RxJS will pick automatically according to the principle of creating
the least concurrency to do the job. Schedulers run tasks according to their own virtual
clock. It has nothing to do with the real world's clock. Many operators facilitate us to set a
Scheduler to meet our needs.
What is a data stream
A stream is data that arrives over some time. The stream of data can be anything. Like variables, user
inputs, properties, caches, data structures, and even failures, etc
Consider the example of a sequence of x & y positions of mouse click events. Assume that the user has
clicked on the locations (12,15), (10,12), (15,20) & (17,15) in that order.
The following diagram shows how the values arrive over a period of time. As you can see, the stream
emits the values as they happen, i.e., asynchronously.

mouse
click events as data streams
Value is not the only thing that stream emits. The stream may complete as the user closes the window or
app. Or an error may happen, resulting in the stream’s closure. At any point in time stream may emit the
following three things.
Value: i.e., the next value in the stream
Complete: The stream has ended
Error: The error has stopped the stream.
The following diagram shows all the three possibilities in a stream

mouse click events as data streams with emit error and complete events
As said earlier the stream of data can be anything. For Example
 Mouse click or Mouse hover events with x & y positions
 Keyboard events like keyup, keydown, keypress, etc
 Form events like value changes etc
 Data which arrives after an HTTP request
 User Notifications
 Measurements from any sensor
Important Points regarding streams can
 Emit zero, one or more values of any time.
 Can also emit errors.
 Must emit the complete signal, when completes (finite streams).
 Can be infinite, that they never complete
Now we have understood what is a data stream, let us look at what is Reactive Programming is
Reactive Programming
Reactive programming is about creating the stream, emitting value, error, or complete signals,
manipulating, transferring, or doing something useful with the data streams.
This is where the RxJs comes into the picture
The introduction to Reactive Programming you’ve been missing gives you a very nice introduction to
Reactive Programming. Also, refer to Introduction to Rx
What is RxJS
The RxJS (Reactive Extensions Library for JavaScript) is a Javascript library that allows us to work with
asynchronous data streams.
Observable in Angular
Angular uses the RxJS library heavily in its framework to implement Reactive Programming. Some of the
examples where reactive programming is used are
 Reacting to an HTTP request in Angular
 Value changes / Status Changes in Angular Forms
 The Router and Forms modules use observables to listen for and respond to user-input events.
 You can define custom events that send observable output data from a child to a parent
component.
 The HTTP module uses observables to handle AJAX requests and responses.
The RxJs has two main players
1. Observable
2. Observers ( Subscribers)
What is an Observable in Angular
Observable is a function that converts the ordinary stream of data into an observable stream of data.
You can think of Observable as a wrapper around the ordinary stream of data.
An observable stream or simple Observable emits the value from the stream asynchronously. It emits
the complete signals when the stream completes or an error signal if the stream errors out.
Observables are declarative. You define an observable function just like any other variable. The
observable starts to emit values only when someone subscribes to it.
Who are observers (subscribers)
The Observable on its own is only useful if someone consumes the value emitted by the observable. We
call them observers or subscribers.
The observers communicate with the Observable using callbacks
The observer must subscribe with the observable to receive the value from the observable. While
subscribing it optionally passes the three callbacks. next(), error() & complete()
Angular Observable Tutorial how
observable and observers communicates with callbacks
The observable starts emitting the value as soon as the observer or consumer subscribes to it.
The observable invokes the next() callback whenever the value arrives in the stream. It passes the value
as the argument to the next callback. If the error occurs, then the error() callback is invoked. It invokes
the complete() callback when the stream completes.
 Observers/subscribers subscribe to Observables
 The observer registers three callbacks with the observable at the time of subscribing.
i .e next(), error() & complete()
 All three callbacks are optional
 The observer receives the data from the observer via the next() callback
 They also receive the errors and completion events from the Observable via
the error() & complete() callbacks
Angular Observable tutorial
Now, we have learned the basics of the RxJs Observable, let us now see how it works using an example.
Create a new project in angular. Remove the contents from app.component.html. Open
the app.component.ts
Import the required libraries
RxJs library is installed automatically when you create the Angular project. Hence there is no need to
install it.
Import the Observable from the rxjs library
1
2 import { Observable } from 'rxjs';
3
Observable Creation
There are a few ways in which you can create observable in angular. The simplest is to use the
Observable constructor. The observable constructor takes the observer (or subscriber) as its argument.
The subscriber will run when this observable’s subscribe() method executes.
The following example creates an observable of a stream of numbers 1, 2, 3, 4, 5
1
2 obs = new Observable((observer) => {
3 console.log("Observable starts")
4 observer.next("1")
5 observer.next("2")
6 observer.next("3")
7 observer.next("4")
8 observer.next("5")
9 })
10
Source Code
The variable obs is now of the type of observable.
The above example declares the obs as observable but does not instantiate it. To make the observable
emit values, we need to subscribe to them.

Creating observable in Angular Observable Tutorial app


In the above example, we used the Observable Constructor to create the Observable. Many operators are
available with the RxJS library, which makes creating the observable easy. These operators help us to
create observables from an array, string, promise, any iterable, etc. Here are list of some of the
commonly used operators
 create
 defer
 empty
 from
 fromEvent
 interval
 of
 range
 throwError
 timer
Subscribing to the observable
We subscribe to the observable by invoking the subscribe method on it.
We either pass an observer object or the next() callback as an argument. The arguments are optional.
The subscribe method signature was changed in RxJs 6.4. Scroll down for older syntax
An observer object is an object that optionally contains the next, error and complete methods. The
signature of the observer object is shown below.
1
2 export interface Observer<T> {
3 next: (value: T) => void;
4 error: (err: any) => void;
5 complete: () => void;
6}
7
The code below shows subscribing to an observable using the observer object. The next method is
invoked whenever the observable emits data. It invokes the error method when an error occurs and
the complete method when the observable completes.
1
2 ngOnInit() {
3 this.obs.subscribe(
4 {
5 next: (val) => {
6 console.log(val);
7 }, //next callback
8 error: (error) => {
9 console.log('error');
10 }, //error callback
11 complete:() => {
12 console.log('Completed');
13 } //complete callback
14 }
15 );
16 }
17
The complete app.component.ts code is as shown below.
1
2 import { Component, OnInit } from '@angular/core';
3 import { Observable } from 'rxjs';
4
5 @Component({
6 selector: 'my-app',
7 template: `
8
9 <h1>Angular Observable Tutorial</h1>
10
11 <br><br><br>
12 Refer
13 <a href="https://www.tektutorialshub.com/angular/angular-observable-tutorial-using-rxjs/">Angular
14 Observable
15 Tutorial</a>
16 `
17 })
18 export class AppComponent implements OnInit {
19
20
21 obs = new Observable(observer => {
22 console.log('Observable starts');
23 observer.next('1');
24 observer.next('2');
25 observer.next('3');
26 observer.next('4');
27 observer.next('5');
28 });
29
30 ngOnInit() {
this.obs.subscribe( {
31
next: (val) => {
32
console.log(val);
33
}, //next callback
34
error: (error) => {
35
console.log('error');
36
}, //error callback
37
complete:() => {
38
console.log('Completed');
39
} //complete callback
40
}
41
);
42
}
43
}
44
45

Prior to RxJs 6.4


The subscribe method signature was changed in RxJs 6.4
To subscribe to an observable, we call the observable’s subscribe() method and pass in an observer or
a next() callback as an argument.
We can optionally, include the three callbacks next(), error() & complete() as shown below
1
2 ngOnInit() {
3
4 this.obs.subscribe(
5 val => { console.log(val) }, //next callback
6 error => { console.log("error") }, //error callback
7 () => { console.log("Completed") } //complete callback
8 )
9 }
10
The complete app.component.ts code is as shown below.
1
2 import { Component, OnInit } from '@angular/core';
3 import { Observable } from 'rxjs';
4
5 @Component({
6 selector: 'app-root',
7 templateUrl: './app.component.html',
8 styleUrls: ['./app.component.css']
9 })
10 export class AppComponent implements OnInit {
11 title = 'Angular Observable using RxJs - Getting Started';
12
13 obs = new Observable((observer) => {
14 console.log("Observable starts")
15 observer.next("1")
16 observer.next("2")
17 observer.next("3")
18 observer.next("4")
19 observer.next("5")
20 })
21
22 data=[];
23
24 ngOnInit() {
25
26 this.obs.subscribe(
27 val=> { console.log(val) },
28 error => { console.log("error")},
29 () => {console.log("Completed")}
30 )
31 }
32 }
33
Source Code
Now, run the code and watch the debug window.
Adding interval
We can add a timeout to insert a delay in each next() callback
1
2 obs = new Observable((observer) => {
3 console.log("Observable starts")
4
5 setTimeout(() => { observer.next("1") }, 1000);
6 setTimeout(() => { observer.next("2") }, 2000);
7 setTimeout(() => { observer.next("3") }, 3000);
8 setTimeout(() => { observer.next("4") }, 4000);
9 setTimeout(() => { observer.next("5") }, 5000);
10
11 })
12
Source Code
Angular Observable tutorial example app
Error event
As mentioned earlier, the observable can also emit an error. This is done by invoking the error() callback
and passing the error object. The observables stop after emitting the error signal. Hence values 4 & 5 are
never emitted.
1
2 obs = new Observable((observer) => {
3 console.log("Observable starts")
4
5 setTimeout(() => { observer.next("1") }, 1000);
6 setTimeout(() => { observer.next("2") }, 2000);
7 setTimeout(() => { observer.next("3") }, 3000);
setTimeout(() => { observer.error("error emitted") }, 3500); //sending error event. observable stops
8
here
9
setTimeout(() => { observer.next("4") }, 4000); //this code is never called
10
setTimeout(() => { observer.next("5") }, 5000);
11
12
})
13

Source Code
You can send the error object as the argument to the error method
Observable with the error event
Complete Event
Similarly the complete event. The observables stop after emitting the complete signal. Hence values 4 &
5 are never emitted.
1
2 obs = new Observable((observer) => {
3 console.log("Observable starts")
4
5 setTimeout(() => { observer.next("1") }, 1000);
6 setTimeout(() => { observer.next("2") }, 2000);
7 setTimeout(() => { observer.next("3") }, 3000);
8 setTimeout(() => { observer.complete() }, 3500); //sending complete event. observable stops here
9 setTimeout(() => { observer.next("4") }, 4000); //this code is never called
10 setTimeout(() => { observer.next("5") }, 5000);
11
12 })
13
Source Code
Observable with complete event
Observable Operators
The Operators are functions that operate on an Observable and return a new Observable.
The power of observable comes from the operators. You can use them to manipulate the incoming
observable, filter it, merge it with another observable, alter the values or subscribe to another
observable.
You can also chain each operator one after the other using the pipe. Each operator in the chain gets the
observable from the previous operator. It modifies it and creates a new observable, which becomes the
input for the next observable.
The following example shows the filer & map operators chained inside a pipe. The filter operator
removes all data which is less than or equal to 2 and the map operator multiplies the value by 2.
The input stream is [1,2,3,4,5] , while the output is [6, 8, 10].
1
2 obs.pipe(
3 obs = new Observable((observer) => {
4 observer.next(1)
5 observer.next(2)
6 observer.next(3)
7 observer.next(4)
8 observer.next(5)
9 observer.complete()
10 }).pipe(
11 filter(data => data > 2), //filter Operator
12 map((val) => {return val as number * 2}), //map operator
13 )
14
The following table lists some of the commonly used operators
AREA OPERATORS
Combination combineLatest, concat, merge, startWith , withLatestFrom, zip
Filtering debounceTime,
distinctUntilChanged, filter,
take, takeUntil, takeWhile, takeLast, first, last, single, skip, skipUntil, skipWhile, skipLast,
Transformation bufferTime, concatMap, map, mergeMap, scan, switchMap, ExhaustMap, reduce
Utility tap, delay, delaywhen
Error Handling throwerror, catcherror, retry, retrywhen
Multicasting share
Unsubscribing from an Observable
We need to unsubscribe to close the observable when we no longer require it. If not it may lead to
memory leak & Performance degradation.
To Unsubscribe from an observable, we need to call the Unsubscribe() method on the subscription. It
will clean up all listeners and frees up the memory.
To do that, first, create a variable to store the subscription
1
2 obs: Subscription;
3
Assign the subscription to the obs variable
1
2
3 this.obs = this.src.subscribe(value => {
4 console.log("Received " + this.id);
5 });
6
7
Call the unsubscribe() method in the ngOnDestroy method.
1
2 ngOnDestroy() {
3 this.obs.unsubscribe();
4}
5
When we destroy the component, the observable is unsubscribed and cleaned up.
But, you do not have to unsubscribe from every subscription. For Example, the observables, which emits
the complete signal, close the observable.
Create observable from a string, array & object in angular
In this tutorial, we will show you how to create observable using create, of, from operators in Angular.
We can use them to create new observable from the array, string, object, collection or any static data.
Also learn the difference between the Of & From operators. If you are new to observable, we recommend
you to read the Angular observable before continuing here.

Table of Contents
 Observable creation functions
 Create
o Observable Constructor
 Of Operator
o observable from an array
o observable from a sequence of numbers
o observable from string
o observable from a value, array & string
 From Operator
o observable from an array
o Observable from string
o Observable from collection
o Observable from iterable
o Observable from promise
 Of Vs From
 References
 Summary
Observable creation functions
There are many ways to create observable in Angular. You can make use of Observable Constructor as
shown in the observable tutorial. There are a number of functions that are available which you can use
to create new observables. These operators help us to create observable from an array, string, promise,
any iterable, etc. Here are some of the operators
 create
 defer
 empty
 from
 fromEvent
 interval
 of
 range
 throw
 timer
All the creation related operators are part of the RxJs core library. You can import it from the ‘rxjs’ library
Create
The Create method is one of the easiest. The create method calls the observable constructor behind the
scene. Create is a method of the observable object, Hence you do not have to import it.
1
2 ngOnInit() {
3
4 //Observable from Create Method
5 const obsUsingCreate = Observable.create( observer => {
6 observer.next( '1' )
7 observer.next( '2' )
8 observer.next( '3' )
9
10 observer.complete()
11 })
12
13 obsUsingCreate
14 .subscribe(val => console.log(val),
15 error=> console.log("error"),
16 () => console.log("complete"))
17 }
18
19
20
21 ****Output *****
22 1
23 2
24 3
25 Complete
26
Observable Constructor
We looked at this in the previous tutorial. There is no difference between the Observable.create method
and observable constructor. The Create method calls the constructor behind the scene.
1
2 ngOnInit() {
3 //Observable Using Constructor
4 const obsUsingConstructor = new Observable( observer => {
5 observer.next( '1' )
6 observer.next( '2' )
7 observer.next( '3' )
8
9 observer.complete()
10 })
11
12 obsUsingConstructor
13 .subscribe(val => console.log(val),
14 error=> console.log("error"),
15 () => console.log("complete"))
16 }
17
18
19 ****Output *****
20 1
21 2
22 3
23 complete
24
Of Operator
The Of creates the observable from the arguments that you pass into it. You can pass any number of
arguments to the Of. Each argument emitted separately and one after the other. It sends
the Complete signal in the end.

To use of you need to import it from rxjs library as shown below.


1
2 import { of } from 'rxjs';
3
observable from an array
Example of sending an array. Note that the entire array is emitted at once.
1
2 ngOnInit() {
3 const array=[1,2,3,4,5,6,7]
4 const obsof1=of(array);
5 obsof1.subscribe(val => console.log(val),
6 error=> console.log("error"),
7 () => console.log("complete"))
8
9 }
10
11
12 **** Output ***
13 [1, 2, 3, 4, 5, 6, 7]
14 complete
15
You can pass more than one array
1
2 ngOnInit() {
3 const array1=[1,2,3,4,5,6,7]
4 const array2=['a','b','c','d','e','f','g']
5 const obsof2=of(array1,array2 );
6 obsof2.subscribe(val => console.log(val),
7 error=> console.log("error"),
8 () => console.log("complete"))
9
10 }
11
12
13 **** Output ***
14 [1, 2, 3, 4, 5, 6, 7]
15 ['a','b','c','d','e','f','g']
16 complete
17
observable from a sequence of numbers
In the following example, we pass 1,2 & 3 as the argument to the from. Each emitted separately.
1
2 ngOnInit() {
3 const obsof3 = of(1, 2, 3);
4 obsof3.subscribe(val => console.log(val),
5 error => console.log("error"),
6 () => console.log("complete"))
7
8 }
9
10
11
12 **** Output ***
13 1
14 2
15 3
16 complete
17
observable from string
We pass two strings to the of method. Each argument is emitted as it is.
1
2 ngOnInit() {
3 const obsof4 = of('Hello', 'World');
4 obsof4.subscribe(val => console.log(val),
5 error => console.log("error"),
6 () => console.log("complete"))
7 }
8
9
10 **** Output ***
11 Hello
12 World
13 complete
14
observable from a value, array & string
We can pass anything to the Of operator. It justs emits it back one after the other.
1
2 ngOnInit() {
3 const obsof5 = of(100, [1, 2, 3, 4, 5, 6, 7],"Hello World");
4 obsof5.subscribe(val => console.log(val),
5 error => console.log("error"),
6 () => console.log("complete"))
7 }
8
9 **** Output ***
10 100
11 [1, 2, 3, 4, 5, 6, 7]
12 Hello World
13 complete
14
From Operator
From Operator takes only one argument that can be iterated and converts it into an observable.
You can use it to convert
 an Array,
 anything that behaves like an array
 Promise
 any iterable object
 collections
 any observable like object
It converts almost anything that can be iterated to an Observable.

To use from you need to import it from rxjs library as shown below.
1
2 import { from } from 'rxjs';
3
observable from an array
The following example converts an array into an observable. Note that each element of the array is
iterated and emitted separately.
1
2 ngOnInit() {
3
4 const array3 = [1, 2, 3, 4, 5, 6, 7]
5 const obsfrom1 = from(array3);
6 obsfrom1.subscribe(val => console.log(val),
7 error => console.log("error"),
8 () => console.log("complete"))
9
10 }
11
12 *** Output ****
13 1
14 2
15 3
16 4
17 5
18 6
19 7
20 complete
21
Observable from string
The from operator iterates over each character of the string and then emits it. The example is as shown
below.
1
2 ngOnInit() {
3 const obsfrom2 = from('Hello World');
4 obsfrom2.subscribe(val => console.log(val),
5 error => console.log("error"),
6 () => console.log("complete"))
7 }
8
9
10 *** Output ****
11 H
12 e
13 l
14 l
15 o
16
17 W
18 o
19 r
20 l
21 d
22 complete
23
Observable from collection
Anything that can be iterated can be converted to observable. Here is an example using a collection.
1
2 ngOnInit() {
3 let myMap = new Map()
4 myMap.set(0, 'Hello')
5 myMap.set(1, 'World')
6 const obsFrom3 = from(myMap);
7 obsFrom3.subscribe(val => console.log(val),
8 error => console.log("error"),
9 () => console.log("complete"))
10 )
11
12 *** output ***
13 [0, "Hello"]
14 [1, "World"]
15 complete
16
Observable from iterable
Any Iterable types like Generator functions can be converted into an observable using from the operator.
1
2 ngOnInit() {
3 const obsFrom4 = from(this.generateNos())
4 obsFrom4.subscribe(val => console.log(val),
5 error => console.log("error"),
6 () => console.log("complete"))
7 }
8
9 *generateNos() {
10 var i = 0;
11 while (i < 5) {
12 i = i + 1;
13 yield i;
14 }
15
16
17 *** Output ***
18 1
19 2
20 3
21 4
22 5
23
Observable from promise
Use it to convert a Promise to an observable
1
2 ngOnInit() {
3 const promiseSource = from(new Promise(resolve => resolve('Hello World!')));
4 const obsFrom5 = from(promiseSource);
5 obsFrom5.subscribe(val => console.log(val),
6 error => console.log("error"),
7 () => console.log("complete"))
8 }
9
10 *** Output ****
11 Hello World
12 complete
13
Of Vs From
Of from
Accepts variable no of arguments Accepts only one argument
emits each argument as it is without changing anything iterates over the argument and emits each value
References
 of API Guide
 from API Guide
 observable
Summary
We can use the Create method or Observable Constructor to create a new observable. The Of operators
is useful when you have array-like values, which you can pass it as a separate argument to Of method to
create an observable. The From Operate tries to iterate anything that passed into it and creates an
observable out of it. There are many other operators or methods available in the RxJS library to create
and manipulate the Angular Observable. We will learn a few of them in the next few tutorials
Create Observable from Event using FromEvent in Angular
Leave a Comment / March 9, 2023 / 3 minutes of reading
Create observable from array, string, number, object & static data

Angular Tutorial

Angular Observable pipe

Angular provides FromEvent method to create an observable from DOM events directly. In this article let
us learn how to do that by creating an observable from the button click event, keyup even & scroll
events.

Table of Contents
 Syntax
 Example of fromEvent
o How it works
 fromevent from button click
 fromevent from scroll
 fromevent from keyup
 Reference
Syntax
1
2 fromEvent<T>(target: FromEventTarget<T>,
3 eventName: string,
4 options: EventListenerOptions,
5 resultSelector: (...args: any[]) => T): Observable<T>
6
FromEventTarget is the first argument to fromevent. It can be a DOM EventTarget, Node.js
EventEmitter, JQuery-like event target, NodeList or HTMLCollection. The target must have a method to
register/unregister the event handler. (addEventListener/ removeEventListener in case of DOM Event
target)
eventName is the second argument, which is a type of event we want to listen to.
Options are the additional argument that we want to pass to , when registering the event handler
i.e addEventListener
resultSelector is optional and will be deprecated in future versions.
Example of fromEvent
To create an observable from any event, first, we need to get the reference to DOM element using
the viewchild & ElementRef. For example the following code gets the reference to the button element
with the id #btn
1
2 //Template
3 <button #btn>Button</button>
4
1
2 //Component
3
4 @ViewChild('btn', { static: true }) button: ElementRef;
5
The code this.button.nativeElement returns the native DOM element. We pass this as the first argument
to the fromEvent to create an observable to the click event.
1
2 buttonClick() {
3 this.buttonSubscription = fromEvent(this.button.nativeElement, 'click')
4 .subscribe(res => console.log(res));
5 }
6
We can invoke the above method from the ngAfterViewInit method. Note that the @ViewChildwill not
initialize the btn element until the ngOnInit Hence we are using the ngAfterViewInit here.
1
2 ngAfterViewInit() {
3 this.buttonClick();
4 }
5
6
How it works
When we subscribe to an observable, which we created using the fromEvent method, it registers the
event handler using the addEventListener in the DOM element. Whenever the user clicks on the
button, fromevent captures the value and emits it to the subscriber as the first argument. When we
unsubscribe, it unregisters the event handler using the removeEventListener.
fromevent from button click
The following is the complete code of fromevent from a button click.
1
2 import { Component, Input, ViewChild, ElementRef, AfterViewInit, OnInit, OnDestroy } from
3 '@angular/core';
4 import { Observable, of, from, fromEvent } from 'rxjs';
5 import { debounceTime } from 'rxjs/operators';
6
7 @Component({
8 selector: 'app-root',
9 templateUrl: './app.component.html',
10 styleUrls: ['./app.component.css']
11 })
12 export class AppComponent implements AfterViewInit , OnInit, OnDestroy {
13
14 title = 'Angular fromEvent Example';
15
16 @ViewChild('btn', { static: true }) button: ElementRef;
17
18 buttonSubscription
19
20 constructor(private elm: ElementRef) {
21 }
22
23 ngOnInit() {
24 }
25
26
27 ngAfterViewInit() {
28 this.buttonClick();
29 }
30
31
32 buttonClick() {
33 this.buttonSubscription = fromEvent(this.button.nativeElement, 'click')
34 .pipe(debounceTime(300))
35 .subscribe(res => console.log(res));
36 }
37
38
ngOnDestroy() {
39
this.buttonSubscription.unsubscribe()
40
}
41
42
}
43

fromevent from scroll


The following code shows how to create observable from the window scroll event
1
2 scroll() {
3 const source = fromEvent(window, 'scroll');
4 source.subscribe(val => console.log(val));
5 }
6
fromevent from keyup
The following code shows how to create observable from a keyUp event.
1
2 //Component
3
4 @ViewChild('name', { static: true }) name: ElementRef;
5
6 ngAfterViewInit() {
7 fromEvent(this.name.nativeElement, 'keyup')
8 .subscribe(res => console.log(res));
9 }
10
Name
Using Angular observable pipe with example
5 Comments / March 9, 2023 / 4 minutes of reading
Observable from event

Angular Tutorial

Angular Map

The pipe method of the Angular Observable is used to chain multiple operators together. We can use
the pipe as a standalone method, which helps us to reuse it at multiple places or as an instance method.
In this tutorial, we will take a look at the pipe and learn how to use it in an Angular Application. We will
show you examples of pipe using map, filter & tap operators.

Table of Contents
 RxJs Operators
 Using pipe to combine operators
o Pipe as an instance method
o Pipe as stand alone method
 References
RxJs Operators
The operators are very important components of the Rxjs library. They are functions that take an
observable as input and transform it into a new observable and return it. We use them to manipulate the
observable data stream.
For Example.
Map operator applies a given project function to each value emitted by the source Observable and emits
the resulting values as an Observable.
Filter operator filter items from the source observable based on some condition and returns the filtered
value as a new observable

The following table lists some of the commonly used operators


AREA OPERATORS
Combination combineLatest, concat, merge, startWith , withLatestFrom, zip
Filtering debounceTime,
distinctUntilChanged, filter,
take, takeUntil, takeWhile, takeLast, first, last, single, skip, skipUntil, skipWhile, skipLast,
Transformation bufferTime, concatMap, map, mergeMap, scan, switchMap, ExhaustMap, reduce
Utility tap, delay, delaywhen
Error Handling throwerror, catcherror, retry, retrywhen
Multicasting Share

BEST ANGULAR BOOKS


The Top 8 Best Angular Books, which helps you to get started with Angular
Using pipe to combine operators
The pipe method accepts operators such as filter, map, as arguments. Each argument must be
separated by a comma. The order of the operators is important because when a user subscribes to an
observable, the pipe executes the operators in a sequence in which they are added.
There are two ways we can use the pipe. One as an instance of observable and the other way is to use if
as standalone method
To use observable we need it to import from the rxjs library. If you are intend to use the pipe standalone
function, then you also need to import it as well. All the operators are available in the
library rxjs/operators.
1
2 import { Observable, of, pipe} from 'rxjs';
3 import { map, filter, tap } from 'rxjs/operators'
4
Pipe as an instance method
The pipe as an instance method is used as below. We the operators op1, op2 etc are passed as the
argument to pipe method. The output of op1 method becomes input of the op2 operator and so forth.
1
2 obs.pipe(
3 op1(),
4 op2(),
5 op3(),
6 op3(),
7)
8
Example : Pipe with Map, Filter & Tap
Here is the example of using pipe with map & filter operator.
1
2 import { Component, OnInit } from '@angular/core';
3 import { Observable, of} from 'rxjs';
4 import { map, filter, tap } from 'rxjs/operators'
5
6
7 @Component({
8 selector: 'app-root',
9 templateUrl: './app.component.html',
10 styleUrls: ['./app.component.css']
11 })
12 export class AppComponent implements OnInit {
13
14 obs = new Observable((observer) => {
15 observer.next(1)
16 observer.next(2)
17 observer.next(3)
18 observer.next(4)
19 observer.next(5)
20 observer.complete()
21 }).pipe(
22 filter(data => data > 2), //filter Operator
23 map((val) => {return val as number * 2}), //map operator
24 )
25
26 data = [];
27
28 ngOnInit() {
29 this.obs1.subscribe(
30 val => {
31 console.log(this.data)
32 }
33 )
34 }
35
36 }
37
38
39 //result
40 [6, 8, 10]
41
The following example makes use of pipe with map, filter & tap operator. The tap operator returns a new
observable which is a mirror copy of the source observable. We use it mostly for debugging purposes
( for example for logging the values of observable as shown below).
1
2 import { Component, OnInit } from '@angular/core';
3 import { Observable, of, pipe } from 'rxjs';
4 import { map, filter, tap } from 'rxjs/operators'
5
6
7 @Component({
8 selector: 'app-root',
9 templateUrl: './app.component.html',
10 styleUrls: ['./app.component.css']
11 })
12 export class AppComponent implements OnInit {
13
14 obs = new Observable((observer) => {
15 observer.next(1)
16 observer.next(2)
17 observer.next(3)
18 observer.next(4)
19 observer.next(5)
20 observer.complete()
21 }).pipe(
22 tap(data => console.log('tap '+data)), //tap
23 filter(data => data > 2), //filter
24 tap(data => console.log('filter '+data)), //tap
25 map((val) => { return val as number * 2 }), //map
26 tap(data => console.log('final '+data)), //tap
27 )
28
29
30 data = [];
31
32 ngOnInit() {
33
34 this.obs.subscribe(
35 val => {
36 this.data.push(val)
37 console.log(this.data)
38 }
39 )
40
41 }
42 }
43
Pipe as stand alone method
We can also use the pipe as a standalone function to compose operators and re use the pipe at other
places.
Example
1
2 import { Component, OnInit } from '@angular/core';
3 import { Observable, of, pipe } from 'rxjs';
4 import { map, filter, tap } from 'rxjs/operators'
5
6
7 @Component({
8 selector: 'app-root',
9 templateUrl: './app.component.html',
10 styleUrls: ['./app.component.css']
11 })
12 export class AppComponent implements OnInit {
13
14
15 customOperator = pipe(
16 tap(data => console.log('tap '+data)),
17 filter(data => data > 2),
18 tap(data => console.log('filter '+data)),
19 map((val) => {
20 return val as number * 2
21 }),
22 tap(data => console.log('final '+data)),
23 );
24
25
26 obs = new Observable((observer) => {
27 observer.next(1)
28 observer.next(2)
29 observer.next(3)
30 observer.next(4)
31 observer.next(5)
32 observer.complete()
33 }).pipe(
34 this.customOperator,
35 tap(data => console.log('final '+data)),
36 )
37
38
39 data = [];
40
41 ngOnInit() {
42
43 this.obs.subscribe(
44 val => {
45 this.data.push(val)
46 console.log(this.data)
47 }
48 )
49
50 }
51 }
52
You can also use the stand alone pipe as shown below.
1
2 customOperator = pipe(
3 tap(data => console.log('tap '+data)),
4 filter(data => data > 2),
5 tap(data => console.log('filter '+data)),
6 map((val) => {
7 return val as number * 2
8 }),
9 tap(data => console.log('final '+data)),
10 );
11
12
13 obs = new Observable((observer) => {
14 observer.next(1)
15 observer.next(2)
16 observer.next(3)
17 observer.next(4)
18 observer.next(5)
19 observer.complete()
20 })
21
22 ngOnInit() {
23 this.customOperator(this.obs).subscribe();
24 }
25
Using Map operator in Angular
3 Comments / March 9, 2023 / 4 minutes of reading
Angular Observable pipe

Angular Tutorial

Filter

The Angular observable Map operator takes an observable source as input. It applies a project function
to each of the values emitted by the source observable and transforms it into a new value. It then emits
the new value to the subscribers. We use a Map with a Pipe, which allows us to chain multiple operators
together. In this guide, we’re going to learn how to use the Map operator with examples like converting
the source to upper case, Using Map the Angular HTTP Request, with DOM events, filtering the input
data, and using multiple Maps together, etc.

Table of Contents
 Syntax
 Using Observable Map
 Map Examples
o Convert input to upper case
o Map to a Single Property
o Using Map with HTTP Request
o Using with event
o map with filter
o Multiple map
 References
Syntax
The syntax of the map operator is as follows.
1
2 map<T, R>(project: (value: T, index: number) => R, thisArg?: any): OperatorFunction<T, R>
3
project: is a function that we use to manipulate the values emitted by the source observable. The project
can accept two arguments. one is value i.e. the value emitted by the observable. The second argument
is index number. The index number starts from 0 for the first value emitted and incremented by one for
every subsequent value emitted. It is similar to the index of an array.
thisArg: is optional and default is undefined.It defines what this is in the project function.
Using Observable Map
To use map first we need to import it from the rxjs/operators library.
1
2 import { map } from 'rxjs/operators'
3
Next, create an observable from array of numbers as shown below.
1
2 srcArray = from([1, 2, 3, 4]);
3
Use the pipe method to and invoke the map method.
1
2 multiplyBy2() {
3 this.srcArray
4 .pipe(map(val => { return val * 2}))
5 .subscribe(val => { console.log(val)})
6 }
7
The project function accepts only one argument val and returns it multiplied by 2.
1
2 map(val => { return val * 2})
3
Finally, we subscribe and print the result in console. The output is 2,4,6,8
The following image explains how values from the source observable ( i.e.1,2,3,4 ) go through
the map which transforms it into new values by multiplying it by 2.

BEST ANGULAR BOOKS


The Top 8 Best Angular Books, which helps you to get started with Angular

You can also access the second argument index as shown below. It starts as 0 for the first value and gets
incremented for every subsequent value
1
2 multiplyBy2() {
3
4 this.srcArray
5 .pipe(map((val, i) => { //index
6 console.log(i) //0
7 return val * 2;
8 }))
9 .subscribe(val => { console.log(val) })
10 }
11
Map Examples
Convert input to upper case
1
2 srcName$ = from(['John', 'Tom', 'Katy'])
3
4 toUpperCase() {
5 this.srcName$
6 .pipe(map(data => {
7 return data.toUpperCase();
8 }))
9 .subscribe(data => console.log(data))
10 }
11
Map to a Single Property
1
2 srcObject = from([
3 { fName: 'Sachin', lName: "Tendulkar" },
4 { fName: 'Rahul', lName: "Dravid" },
5 { fName: 'Saurav', lName: "Ganguly" },
6 ]);
7
8
9 MapToSingleProperty() {
10 this.srcObject
11 .pipe(map(data => { return data.fName + ' ' + data.lName }))
12 .subscribe(data => { console.log(data) })
13 }
14
15 //output
16 Sachin Tendulkar
17 Rahul Dravid
18 Saurav Ganguly
19
Using Map with HTTP Request
The following code gets the list of dogs breeds from the https://dog.ceo/api/breeds/list/all API and
uses the keyValue pipe to transform the object into an array of key-value pairs.
1
2 import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
3 import { Observable, from, pipe, fromEvent } from 'rxjs';
4 import { map, filter, tap } from 'rxjs/operators'
5 import { HttpClient } from '@angular/common/http';
6 import { KeyValuePipe } from '@angular/common';
7
8 @Component({
9 selector: 'app-root',
10 templateUrl: './app.component.html',
11 styleUrls: ['./app.component.css'],
12 providers: [KeyValuePipe]
13 })
14 export class AppComponent implements OnInit {
15
16 constructor(private http: HttpClient,
17 private keyValue: KeyValuePipe) {
18 }
19
20 @ViewChild('btn', { static: true }) button: ElementRef;
21
22 $dogsBreed(): Observable<any> {
23 return this.http.get<any>("https://dog.ceo/api/breeds/list/all")
24 }
25
26 getDogsBreed() {
27
28 this.$dogsBreed()
29 .pipe(map(data => {
30 var dogs = this.keyValue.transform(data.message)
31 console.log(dogs)
32 }))
33 .subscribe();
34
35 }
36 }
37
Using with event
You can create observable from event and use the map to transform the values.
1
2 buttonClick() {
3 fromEvent(this.button.nativeElement, 'click')
4 .pipe(map( ev => (ev as any).clientX))
5 .subscribe(res => console.log(res));
6 }
7
map with filter
1
2 srcArray = from([1, 2, 3, 4]);
3
4 filterWithMap() {
5 this.srcArray
6 .pipe(
7 filter(val => {
8 return val > 2;
9 }),
10 map((val, i) => {
11 return val * 2;
12 }))
13 .subscribe(val => { console.log(val) })
14 }
15
Multiple map
The following examples shows use of multiple map functions. The first map adds 10, while the second
mad multiplies by 2.
1
2
mulitpleMaps() {
3
this.srcArray
4
.pipe(
5
map(val => {
6
return val + 10;
7
}),
8
map((val, i) => {
9
return val * 2;
10
}))
11
.subscribe(val => { console.log(val) })
12
}
13

Tap operator in Angular observable


Leave a Comment / March 9, 2023 / 3 minutes of reading
Filter

Angular Tutorial

SwitchMap

The Angular Tap RxJs operator returns an observable that is identical to the source. It does not
modify the stream in any way. Tap operator is useful for logging the value, debugging the stream for the
correct values, or perform any other side effects.

Syntax
1
2 tap(nextOrObserver: function, error: function, complete: function): Observable
3
Table of Contents
 Tap Operator Example
 Debugging the Observable
 Error & Complete callbacks
 Reference
Tap Operator Example
In the following example, we create an observable using the of operator. We use the pipe to chain the tap
operator, which just logs the values of the source observable into the console.
1
2 import { Component, VERSION } from "@angular/core";
3 import { tap } from "rxjs/operators";
4 import { of } from "rxjs";
5
6 @Component({
7 selector: "my-app",
8 template: `
9 <h1>Tap Example</h1>
10 `,
11 styleUrls: ["./app.component.css"]
12 })
13 export class AppComponent {
14 ngOnInit() {
15 of(1, 2, 3, 4, 5)
16 .pipe(
17 tap(val => {
18 console.log("Tap " + val);
19 })
20 )
21 .subscribe(val => console.log("at Subscriber " + val));
22 }
23
24 }
25
26
27
28
29 ***Console
30
31 Tap 1
32 at Subscriber 1
33 Tap 2
34 at Subscriber 2
35 Tap 3
36 at Subscriber 3
37 Tap 4
38 at Subscriber 4
39 Tap 5
40 at Subscriber 5
41
42
Source Code
if we simply pass the console.log function to the tap operator and the results will be same.
1
2 of(1, 2, 3, 4, 5)
3 .pipe(tap(console.log))
4 .subscribe(val => console.log("at Subscriber " + val));
5
Tap does not modify the source observable in any way
For Example changing the source any way in the tap operator as in the example below, will have no
effect.
1
2 of(1, 2, 3, 4, 5)
3 .pipe(
4 tap(val => {
5 val=val+1
6 console.log("Tap " + val);
7 return val;
8 })
9 )
10 .subscribe(val => console.log("at Subscriber " + val));
11
Debugging the Observable
One of the use cases for the tap operator is using it to debug the Observable for the correct values.
The map operator in the following example, adds 5 to the source observable. To debug it, we can add the
two tap operators. One before and one after it and inspect the values.
1
2 of(1, 2, 3, 4, 5)
3 .pipe(
4 tap(val => {
5 console.log("before " +val);
6 }),
7 map(val => {
8 return val + 5;
9 }),
10 tap(val => {
11 console.log("after " +val);
12 })
13 )
14 .subscribe(val => console.log(val));
15
16
17
18 **Console**
19 before 1
20 after 6
21 6
22 before 2
23 after 7
24 7
25 before 3
26 after 8
27 8
28
Source Code
Error & Complete callbacks
We can also use the tap operator to log the error and complete callbacks as shown in the example below.
1
2 import { Component, VERSION } from "@angular/core";
3 import { FormControl, FormGroup } from "@angular/forms";
4 import { debounce, map, tap } from "rxjs/operators";
5 import { interval, of, Subscription } from "rxjs";
6
7 @Component({
8 selector: "my-app",
9 template: `
10 <h1>Tap Example</h1>
11
12
13 `,
14 styleUrls: ["./app.component.css"]
15 })
16 export class AppComponent {
17 ngOnInit() {
18 of(1, 2, 3, 4, 5)
19 .pipe(
20 tap(val => {
21 console.log("Before " + val);
22 }),
23 map(val => {
24 if (val == 3) {
25 throw Error;
26 }
27 return val + 5;
28 }),
29 tap(
30 val => {
31 console.log("After " + val);
32 },
33 err => {
34 console.log("Tap Error");
35 console.log(err);
36 },
37 () => {
38 console.log("Tap Complete");
39 }
40 )
41 )
42 .subscribe(val => console.log(val));
43 }
44
45 ngOnDestroy() {}
46 }
47
48
49 ***Console ***
50 Before 1
51 After 6
52 6
53 Before 2
54 After 7
55
7
56
Before 3
57
Tap Error
58
ƒ Error()
59
60
ERROR
61
ƒ Error()
62

Using SwitchMap in Angular


11 Comments / March 9, 2023 / 6 minutes of reading
Angular Tap

Angular Tutorial

Angular MergeMap

The Angular SwitchMap maps each value from the source observable into an inner observable,
subscribes to it, and then starts emitting the values from it. It creates a new inner observable for every
value it receives from the Source. Whenever it creates a new inner observable it unsubscribes from all
the previously created inner observables. Basically it switches to the newest observable discarding all
other.

Table of Contents
 Syntax
 SwitchMap Example
 SwitchMap Vs Map
 SwitchMap switches to the most recent observable
 Using SwitchMap in Angular
o With Route Parameters
o Angular Forms ValueChanges event
 References
Syntax
The syntax of the SwitchMap operator is as shown below.
1
2 switchMap(project: (value: T, index: number) => O): OperatorFunction<T, ObservedValueOf<O>>
3
project: is a function that we use to manipulate the values emitted by the source observable. The project
can accept two arguments. one is value i.e. the value emitted by the source observable. The second
argument is index number. The index number starts from 0 for the first value emitted and incremented
by one for every subsequent value emitted. It is similar to the index of an array. The project function
must return an observable.
SwitchMap Example
To use SwitchMap in Angular first we need to import it our Component or Service.
1
2 import { switchMap } from 'rxjs/operators';
3
The following code shows how to use SwitchMap in Angular. We have two
observables srcObservable which emits 1,2,3,4 & innerObservable which emits 'A','B','C','D'.

BEST ANGULAR BOOKS


The Top 8 Best Angular Books, which helps you to get started with Angular
1
2 let srcObservable= of(1,2,3,4)
3 let innerObservable= of('A','B','C','D')
4
5 srcObservable.pipe(
6 switchMap( val => {
7 console.log('Source value '+val)
8 console.log('starting new observable')
9 return innerObservable
10 })
11 )
12 .subscribe(ret=> {
13 console.log('Recd ' + ret);
14 })
15
16
17 //Output
18 Source value 1
19 starting new observable
20 Recd A
21 Recd B
22 Recd C
23 Recd D
24 Source value 2
25 starting new observable
26 Recd A
27 Recd B
28 Recd C
29 Recd D
30 Source value 3
31 starting new observable
32 Recd A
33 Recd B
34 Recd C
35 Recd D
36 Source value 4
37 starting new observable
38 Recd A
39 Recd B
40 Recd C
41 Recd D
42
The project function is the first argument to the switchMap. It takes the values from the srcObservable.
For each value, it receives from the srcObservable (i. e. 1,2,3 &4) it creates a new observable
i.e. innerObservable.
SwitchMap automatically subscribes to the innerObservable returned by the project function. The
innerObservable emits the values (A,B,C,D), and pushes it to the stream
Hence the subscribers will receive the values A, B, C, D four times. Once for each value of
the srcObservable.
SwitchMap Vs Map
The map operators emits value as observable. The SwitchMap creates a inner observable, subscribes to
it and emits its value as observable.
The Following example shows the difference between them.
The map operator below maps the value coming from the source observable to a new value by
multiplying it by 2. It then emits it into the observable stream. The subscribers will receive the values
2,4,6 & 8.
1
2 let obs= of(1,2,3,4)
3
4 //Using MAP
5 obs.pipe(
6 map(val => {
7 return val*2 //Returning Value
8 })
9 )
10 .subscribe(ret=> {
11 console.log('Recd from map : ' + ret);
12 })
13
14 //Output
15 Recd from map : 2
16 Recd from map : 4
17 Recd from map : 6
18 Recd from map : 8
19
We can write the above code using SwitchMap as follows. The only thing that changes is how we return
the new value in the project function. The map example returns the value as val*2, while the SwitchMap
returns new observable (of(val*2)) using the of function. It also subscribes to the newly created
observable and emits its value to the stream.
1
2 let obs= of(1,2,3,4)
3
4 obs.pipe(
5 switchMap( val => {
6 return of(val*2) //Returning observable
7 })
8 )
9 .subscribe(ret=> {
10 console.log('Recd from switchMap : ' + ret);
11 })
12
13 //Output
14 Recd from switchMap : 2
15 Recd from switchMap : 4
16 Recd from switchMap : 6
17 Recd from switchMap : 8
18
SwitchMap switches to the most recent observable
Whenever SwitchMap subscribes to a new inner observable, it unsubscribes from the previous one.
In the following example, we create an observable from the click event of a button using
the fromEvent method. The SwitchMap operator returns an observable using the interval method.
The interval method creates an infinite observable, which emits a sequence of integers spaced by a given
time interval.
1
2 import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
3 import { of, from, fromEvent, interval, Observable } from 'rxjs';
4 import { switchMap, map, catchError } from 'rxjs/operators';
5
6 @Component({
7 selector: 'app-root',
8 template: `<button #button>Click Me</button>`,
9 })
10 export class AppComponent implements AfterViewInit{
11
12 @ViewChild('button',{static:true}) button;
13 clicks$:Observable<any>;
14
15 ngAfterViewInit() {
16 this.clicks$ = fromEvent(this.button.nativeElement, 'click');
17 this.switchExample();
18 }
19
20 switchExample() {
21 this.clicks$
22 .pipe(
23 switchMap(() => {
24 return interval(500)
25 })
26 )
27 .subscribe( val => console.log(val));
28 }
29 }
30
When you click on the button, the clicks observable emits its first value. The switchMap replaces it with
the interval observable, which starts emitting value starting from 0 every 500ms.
When you click again, the switchMap unsubscribes from the previous interval observable and starts new
one, which again starts to emit value from 0.

Using SwitchMap in Angular


The following are some of the real use cases for the SwitchMap in Angular
With Route Parameters
When we use the Angular Router to Pass parameter to route, we need to read it in our component class.
We do that by subscribing to the paramMap to get the id. We then use the id to retrieve
the product data.
The code is as shown below.
1
2 ngOnInit() {
3 this._Activatedroute.paramMap.subscribe(params => {
4 this.service.getProduct(+params.get('id'))
5 .subscribe((product: Product) => this.product = product);
6 });
7 }
8
Consider the example where the user navigates to the /product/1 route. The service will send the query
to the database to get the Product with id 1. Now, the user decides to navigate to the route /product/2.
This will also result in another query for the Product being sent to the database. It is possible that the
result of the second query arrives before the first query. In such a scenario, we will be in the
route /product/2 , while our component displays the data of the product 1.
We can easily solve the above issue using the switchMap. When SwitchMap creates the second
observable it unsubscribes from all the previous observable. Hence even if the Product 1 data arrives
late, it would be discarded as there are no subscribers
1
2 ngOnInit() {
3
4 this.activatedRoute.paramMap
5 .pipe(
6 switchMap((params: Params) => {
7 return this.service.getProduct(params.get('id'))
8 }
9 ))
10 .subscribe((product: Product) => this.product = product);
11 }
12
Angular Forms ValueChanges event
The similar situations described above can also happen when we subscribe to the ValueChanges event
and use that to get data from the back end.
1
2 this.mainForm.get("productCode").valueChanges
3 .pipe(
4 debounceTime(700)
5 )
6 .subscribe(val=> {
7 this.queryDepositData(val)
8 .subscribe(data => {
9 this.product=data;
10 })
11 })
12
The switchMap ensures that only the result from the last observable populates the Product
1
2 this.mainForm.get("productCode").valueChanges
3 .pipe(
4 debounceTime(700),
5 switchMap(val => {
6 return this.queryDepositData();
7 })
8 )
9 .subscribe(data => {
10 this.product=data;
11 })
12
The example also uses the debounceTime operator, which emits a value from the source Observable
only after a particular time span has passed without another source emission.
Using MergeMap in Angular
5 Comments / March 9, 2023 / 6 minutes of reading
Angular SwitchMap

Angular Tutorial

Angular ConcatMap

The Angular MergeMap maps each value from the source observable into an inner observable,
subscribes to it, and then starts emitting the values from it replacing the original value. It creates a new
inner observable for every value it receives from the Source. Unlike SwitchMap, MergeMap does not
cancel any of its inner observables. It merges the values from all of its inner observables and emits the
values back into the stream.

Table of Contents
 Syntax
 MergeMap Example
 MergeMap Vs Map
 MergeMap combines results of inner observable
 Using MergeMap in Angular
o Merging values from two or more HTTP Calls
o Using ForkJoin with MergeMap
 References
Syntax
The syntax of the MergeMap operator is as shown below.
1
2 mergeMap(project: (value: T, index: number) => O): OperatorFunction<T, ObservedValueOf<O>>
3
project: is a function that we use to manipulate the values emitted by the source observable. The project
function accepts two arguments. one is value i.e. the value emitted by the source observable. The
second argument is index number. The index number starts from 0 for the first value emitted and
incremented by one for every subsequent value emitted. It is similar to the index of an array. The project
function must return an observable.
MergeMap Example
To use MergeMap in Angular first we need to import it our Component or Service.
1
2 import { mergeMap } from 'rxjs/operators';
3
The following code shows how to use MergeMap in Angular. We have two
observables srcObservable which emits 1,2,3,4 & innerObservable which emits 'A','B','C','D'.
1
2 let srcObservable= of(1,2,3,4)
3 let innerObservable= of('A','B','C','D')
4
5 srcObservable.pipe(
6 mergeMap( val => {
7 console.log('Source value '+val)
8 console.log('starting new observable')
9 return innerObservable
10 })
11 )
12 .subscribe(ret=> {
13 console.log('Recd ' + ret);
14 })
15
16
17 //Output
18 Source value 1
19 starting new observable
20 Recd A
21 Recd B
22 Recd C
23 Recd D
24 Source value 2
25 starting new observable
26 Recd A
27 Recd B
28 Recd C
29 Recd D
30 Source value 3
31 starting new observable
32 Recd A
33 Recd B
34 Recd C
35 Recd D
36 Source value 4
37 starting new observable
38 Recd A
39 Recd B
40 Recd C
41 Recd D
42

BEST ANGULAR BOOKS


The Top 8 Best Angular Books, which helps you to get started with Angular
The project function is the first argument to the MergeMap. It takes the values from the srcObservable.
For each value, it receives from the srcObservable (i. e. 1,2,3 &4) it creates a new observable
i.e. innerObservable.
MergeMap automatically subscribes to the innerObservable returned by the project function.
The innerObservable emits the values (A, B, C, D), and pushes it to the stream
Hence the subscribers will receive the values A, B, C, D four times. Once for each value of
the srcObservable.
MergeMap Vs Map
The map operators emit value as observable. The MergeMap creates an inner observable, subscribes to
it, and emits its value as observable.
The Following example shows the difference between MergeMap & Map.
The Map operator below maps the value coming from the source observable to a new value by
multiplying it by 2. It then emits it into the observable stream. The subscribers will receive the values 2,
4, 6 & 8.
1
2 let obs= of(1,2,3,4)
3
4 //Using MAP
5 obs.pipe(
6 map(val => {
7 return val*2 //Returning Value
8 })
9 )
10 .subscribe(ret=> {
11 console.log('Recd from map : ' + ret);
12 })
13
14 //Output
15 Recd from map : 2
16 Recd from map : 4
17 Recd from map : 6
18 Recd from map : 8
19
We can achieve the same using the MergeMap also. The only thing that changes is how we return the new
value from our project function. The map returns the value as val*2, while the MergeMap returns the
value as observable (of(val*2)) using the of function. It also subscribes to the newly created observable
and emits its value to the stream.
1
2 let obs= of(1,2,3,4)
3
4 obs.pipe(
5 mergeMap( val => {
6 return of(val*2) //Returning observable
7 })
8 )
9 .subscribe(ret=> {
10 console.log('Recd from mergeMap : ' + ret);
11 })
12
13 //Output
14 Recd from mergeMap: 2
15 Recd from mergeMap: 4
16 Recd from mergeMap: 6
17 Recd from mergeMap: 8
18
MergeMap combines results of inner observable
MergeMap never cancels any of its inner observable. It waits for them to finish and emit value. Note that
the inner observable’s might finish in an order that is different from the order in which they are
subscribed. MergeMap does not care about the order.
In the following example, we create an observable from the click event of a button using
the fromEvent method. On every click of the button, the MergeMap operator returns an inner
observable delayedObs
The delayedObs emits 5 values separated by 1000 ms.
1
2 import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
3 import { of, from, fromEvent, interval, Observable } from 'rxjs';
4 import { switchMap, map, catchError } from 'rxjs/operators';
5
6 @Component({
7 selector: 'app-root',
8 template: `<button #button>Click Me</button>`,
9 })
10 export class AppComponent implements AfterViewInit{
11
12 @ViewChild('button',{static:true}) button;
13 clicks$:Observable<any>;
14
15 ngAfterViewInit() {
16 this.clicks$ = fromEvent(this.button.nativeElement, 'click');
17 this.mergeMapExample();
18 }
19
20 delayedObs(count:number) {
21 return new Observable((observer) => {
22 setTimeout(() => { observer.next(count+" A") }, 1000);
23 setTimeout(() => { observer.next(count+" B") }, 2000);
24 setTimeout(() => { observer.next(count+" C") }, 3000);
25 setTimeout(() => { observer.next(count+" D") }, 4000);
26 setTimeout(() => { observer.next(count+" E"); observer.complete() }, 5000);
27 })
28 }
29
30 mergeMapExample() {
31
32 let obs=
33
34 this.clicks$
35 .pipe(
36 mergeMap(() => {
37 this.count=this.count+1;
38 return this.delayedObs(this.count)
39 })
40 )
41 .subscribe(val => console.log(val));
42 }
43
44 }
45
When you click on the button, the clicks observable emits its first value. Inside the MergeMap we
increase the count by 1 and pass it to the delayedObs. The mergeMap subscribes to the delayedObs. It
starts emitting values A to E prepended by the count.
When you click again, the mergeMap again subscribes to the delayedObs and it starts to emit the
values again.
The mergeMap collects all the emitted values as they arrive from all of its inner observables and emits it
into the subscribers.
Using MergeMap in Angular
The following are some of the real use cases for the MergeMap in Angular
Merging values from two or more HTTP Calls
Consider a scenario where you receive data from an observable (outer observable). For each of those
values, you want to call another observable (inner observable) to get more data. The scenario like this is
an ideal use case for MergeMap
In the following example, we have an array of a breed of dogs. We convert the array into an observable.
This becomes our outer observable
For each of those dog breeds emitted by the outer observable, we make an HTTP request to get the sub-
breeds using the free Dog API. The URL for the HTTP request constructed using the dog breed, which we
receive from the outer observable.
The MergeMap automatically subscribes to all of its inner observable and waits for them to complete. It
then pushes the values from them into the subscribers.
1
2 of("hound", "mastiff", "retriever") //outer observable
3 .pipe(
4 mergeMap(breed => {
5 const url = 'https://dog.ceo/api/breed/' + breed + '/list';
6 return this.http.get<any>(url) //inner observable
7 })
8 )
9 .subscribe(data => {
10 console.log(data)
11 })
12
The above code, without using the MergeMap is as follows. The code makes use of nested observable.
1
2 of("hound", "mastiff", "retriever")
3 .subscribe(breed => {
4 const url = 'https://dog.ceo/api/breed/' + breed + '/list';
5
6 this.http.get<any>(url)
7 .subscribe(data => {
8 console.log(data)
9 })
10 })
11
Using ForkJoin with MergeMap
The MergeMap create a one inner observable for each value of outer observable. To Create more than
one inner observable, we can make use of the ForkJoin Operator.
In the following example, along with a list of breeds, we also send a query for a random image of the dog
breed. This requires us to send two HTTP get request in Angular. We create two
observables obs1 & obs2 to do that. Then we use the forJoin to merge obs1 with obs2 and return a new
observable.
1
2 MergeHTTPRequestWithFork() {
3
4 //const url='https://dog.ceo/api/breed/'+hound+'/list';
5
6 of("hound", "mastiff", "retriever")
7 .pipe(
8 mergeMap(breed => {
9 const url1 = 'https://dog.ceo/api/breed/' + breed + '/list';
10 const url2 = 'https://dog.ceo/api/breed/' + breed + '/images/random';
11
12 let obs1= this.http.get<any>(url1)
13 let obs2= this.http.get<any>(url2)
14
15 return forkJoin(obs1,obs2)
16
17 })
18 )
19
.subscribe(data => {
20
console.log(data)
21
})
22
23
}
24
Using concatMap in Angular
3 Comments / March 9, 2023 / 7 minutes of reading
Angular MergeMap

Angular Tutorial

Angular exhaustMap

The Angular ConcatMap maps each value from the source observable into an inner observable,
subscribes to it, and then starts emitting the values from it replacing the original value. It creates a new
inner observable for every value it receives from the Source. It merges the values from all of its inner
observables in the order in which they are subscribed and emits the values back into the stream.
Unlike SwitchMap, ConcatMap does not cancel any of its inner observables. It is Similar
to MergeMap except for one difference that it maintains the order of its inner observables.

Table of Contents
 Syntax
 ConcatMap Example
 ConcatMap Vs Map
 ConcatMap combines inner observable and keeps the order
 Using ConcatMap in Angular
o Merging values from two or more HTTP Calls
o Using ForkJoin with ConcatMap
 References
Syntax
The syntax of the concatMap operator is as shown below.
1
2 concatMap(project: (value: T, index: number) => O): OperatorFunction<T, ObservedValueOf<O>>
3
project: is a function that we use to manipulate the values emitted by the source observable. The project
function accepts two arguments. one is value i.e. the value emitted by the source observable. The
second argument is index number. The index number starts from 0 for the first value emitted and
incremented by one for every subsequent value emitted. It is similar to the index of an array. The project
function must return an observable.
ConcatMap Example
To use concatMap in Angular first we need to import it our Component or Service.
1
2 import { concatMap } from 'rxjs/operators';
3
In the following code, we have two observables srcObservable which
emits 1,2,3,4 & innerObservable which emits 'A','B','C','D'.
1
2 let srcObservable= of(1,2,3,4)
3 let innerObservable= of('A','B','C','D')
4
5 srcObservable.pipe(
6 concatMap( val => {
7 console.log('Source value '+val)
8 console.log('starting new observable')
9 return innerObservable
10 })
11 )
12 .subscribe(ret=> {
13 console.log('Recd ' + ret);
14 })
15
16
17 //Output
18 Source value 1
19 starting new observable
20 Recd A
21 Recd B
22 Recd C
23 Recd D
24 Source value 2
25 starting new observable
26 Recd A
27 Recd B
28 Recd C
29 Recd D
30 Source value 3
31 starting new observable
32 Recd A
33 Recd B
34 Recd C
35 Recd D
36 Source value 4
37 starting new observable
38 Recd A
39 Recd B
40 Recd C
41 Recd D
42

BEST ANGULAR BOOKS


The Top 8 Best Angular Books, which helps you to get started with Angular
The ConcatMap receives its values from the srcObservable. For each value, it creates a new observable
i.e. innerObservable. It also automatically subscribes to the innerObservable.
The innerObservable emits the values (A, B, C, D), and pushes it to the subscribers.
The ConcactMap differs from the MergeMap, the way it handles the inner observable. ConcatMap always
waits for the previous inner observable to finish before creating a new observble. This will ensure that
the subscribers will receive the data in the order in which the observable’s are subscribed.
Hence the subscribers will receive the values A, B, C, D four times. Once for each value of
the srcObservable.
ConcatMap Vs Map
The map operators emit value as observable. The ConcatMap creates an inner observable, subscribes to
it, and emits its value as observable. It emits the value in the order in which it creates the observable.
The Following example shows the difference between ConcatMap & Map.
The Map operator below maps the value coming from the source observable to a new value by
multiplying it by 2. It then emits it into the observable stream. The subscribers will receive the values 2,
4, 6 & 8.
1
2 let obs= of(1,2,3,4)
3
4 //Using MAP
5 obs.pipe(
6 map(val => {
7 return val*2 //Returning Value
8 })
9 )
10 .subscribe(ret=> {
11 console.log('Recd from map : ' + ret);
12 })
13
14 //Output
15 Recd from map : 2
16 Recd from map : 4
17 Recd from map : 6
18 Recd from map : 8
19
In the ConcatMap example, only thing that changes is how we return the new value from our project
function. The map returns the value as val*2, while the concatMap returns the value as observable
(of(val*2)) using the of function. It also subscribes to the newly created observable and emits its value to
the stream.
1
2 let obs= of(1,2,3,4)
3
4 obs.pipe(
5 concatMap( val => {
6 return of(val*2) //Returning observable
7 })
8 )
9 .subscribe(ret=> {
10 console.log('Recd from concatMap : ' + ret);
11 })
12
13 //Output
14 Recd from concatMap: 2
15 Recd from concatMap: 4
16 Recd from concatMap: 6
17 Recd from concatMap: 8
18
ConcatMap combines inner observable and keeps the order
ConcatMap never cancels any of its inner observable. It waits for them to finish and emit value. It also
waits for the previous inner observable to finish before creating a new observable.
In the following example, we create an observable from the click event of a button using
the fromEvent method. On every click of the button, the ConcatMap operator returns an inner
observable delayedObs
The delayedObs emits 5 values separated by 1000 ms.
1
2 import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
3 import { of, from, fromEvent, interval, Observable } from 'rxjs';
4 import { switchMap, map, catchError } from 'rxjs/operators';
5
6 @Component({
7 selector: 'app-root',
8 template: `<button #button>Click Me</button>`,
9 })
10 export class AppComponent implements AfterViewInit{
11
12 @ViewChild('button',{static:true}) button;
13 clicks$:Observable<any>;
14
15 ngAfterViewInit() {
16 this.clicks$ = fromEvent(this.button.nativeElement, 'click');
17 this.concatMapExample3();
18 }
19
20 delayedObs(count:number) {
21 return new Observable((observer) => {
22 setTimeout(() => { observer.next(count+" A") }, 1000);
23 setTimeout(() => { observer.next(count+" B") }, 2000);
24 setTimeout(() => { observer.next(count+" C") }, 3000);
25 setTimeout(() => { observer.next(count+" D") }, 4000);
26 setTimeout(() => { observer.next(count+" E"); observer.complete() }, 5000);
27 })
28 }
29
30 concatMapExample3() {
31
32 let obs=
33
34 this.clicks$
35 .pipe(
36 concatMap(() => {
37 this.count=this.count+1;
38 return this.delayedObs(this.count)
39 })
40 )
41 .subscribe(val => console.log(val));
42 }
43
44 }
45
When you click on the button, the clicks observable emits its first value. Inside the concatMap we
increase the count by 1 and pass it to the delayedObs. The concatMap subscribes to the delayedObs. It
starts emitting values A to E prepended by the count.
When you click again, the concatMap checks if the previous observable has finished. If not it waits for it
to finish before subscribing to the delayedObs
The concatMap collects all the emitted values from all of its inner observables and emits it into the
subscribers.
You can verify from the following result that even though we click multiple times on the click button, the
results always appear in the correct order.
Using ConcatMap in Angular
The following are some of the real use cases for the concatMap in Angular
Merging values from two or more HTTP Calls
Consider a scenario where you receive data from an observable (outer observable). For each of those
values, you want to call another observable (inner observable) to get more data. The scenario like this is
an ideal use case for ConcatMap
In the following example, we have an array of a breed of dogs. We convert the array into an observable.
This becomes our outer observable
For each of those dog breeds emitted by the outer observable, we make an HTTP request to get the sub-
breeds using the free Dog API. The URL for the HTTP request constructed using the dog breed, which we
receive from the outer observable.
The ConcatMap automatically subscribes to all of its inner observable and waits for them to complete. It
then pushes the values from them into the subscribers.
1
2 of("hound", "mastiff", "retriever") //outer observable
3 .pipe(
4 concatMap(breed => {
5 const url = 'https://dog.ceo/api/breed/' + breed + '/list';
6 return this.http.get<any>(url) //inner observable
7 })
8 )
9 .subscribe(data => {
10 console.log(data)
11 })
12
The above code, without using the concatMap is as follows. The code makes use of nested observable.
1
2 of("hound", "mastiff", "retriever")
3 .subscribe(breed => {
4 const url = 'https://dog.ceo/api/breed/' + breed + '/list';
5
6 this.http.get<any>(url)
7 .subscribe(data => {
8 console.log(data)
9 })
10 })
11
Using ForkJoin with ConcatMap
The ConcatMap create a one inner observable for each value of outer observable. To Create more than
one inner observable, we can make use of the ForkJoin Operator.
In the following example, along with a list of breeds, we also send a query for a random image of the dog
breed. This requires us to send two HTTP get request in Angular. We create two
observables obs1 & obs2 to do that. Then we use the forJoin to merge obs1 with obs2 and return a new
observable.
1
2 MergeHTTPRequestWithFork() {
3
4 //const url='https://dog.ceo/api/breed/'+hound+'/list';
5
6 of("hound", "mastiff", "retriever")
7 .pipe(
8 concatMap(breed => {
9 const url1 = 'https://dog.ceo/api/breed/' + breed + '/list';
10 const url2 = 'https://dog.ceo/api/breed/' + breed + '/images/random';
11
12 let obs1= this.http.get<any>(url1)
13 let obs2= this.http.get<any>(url2)
14
15 return forkJoin(obs1,obs2)
16
17 })
18 )
19 .subscribe(data => {
20 console.log(data)
21 })
22
23 }
24
Using ExhaustMap in Angular
Leave a Comment / March 9, 2023 / 4 minutes of reading
Angular ConcatMap

Angular Tutorial

Take, TakeUntil, takeWhile & TakeLast

The Angular ExhaustMap maps each value from the source observable into an inner observable,
subscribes to it. It then starts emitting the values from it replacing the original value. It then waits for the
inner observable to finish. If it receives any new values before the completion of the inner observable it
ignores it. It receives a new value after completion of the inner observable, then it creates a new inner
observable. The whole process repeats itself until the source observable is completes

Table of Contents
 Syntax
 ExhaustMap Example
 ExhaustMap waits for the inner observable to finish
 Using ExhaustMap in Angular
 References
Syntax
The syntax of the exhaustMap operator is as shown below.
1
2 exhaustMap(project: (value: T, index: number) => O): OperatorFunction<T, ObservedValueOf<O>>
3
project: is a function that we use to manipulate the values emitted by the source observable. The project
function accepts two arguments. one is value i.e. the value emitted by the source observable. The
second argument is index number. The index number starts from 0 for the first value emitted and
incremented by one for every subsequent value emitted. It is similar to the index of an array. The project
function must return an observable.
ExhaustMap Example
To use ExhaustMap in Angular first we need to import it our Component or Service.
1
2 import { exhaustMap} from 'rxjs/operators';
3
In the following code, we have two observables srcObservable which
emits 1,2,3,4 & innerObservable which emits 'A','B','C','D'.

BEST ANGULAR BOOKS


The Top 8 Best Angular Books, which helps you to get started with Angular
1
2 let srcObservable= of(1,2,3,4)
3 let innerObservable= of('A','B','C','D')
4
5 srcObservable.pipe(
6 exhaustMap( val => {
7 console.log('Source value '+val)
8 console.log('starting new observable')
9 return innerObservable
10 })
11 )
12 .subscribe(ret=> {
13 console.log('Recd ' + ret);
14 })
15
16
17 //Output
18 Source value 1
19 starting new observable
20 Recd A
21 Recd B
22 Recd C
23 Recd D
24 Source value 2
25 starting new observable
26 Recd A
27 Recd B
28 Recd C
29 Recd D
30 Source value 3
31 starting new observable
32 Recd A
33 Recd B
34 Recd C
35 Recd D
36 Source value 4
37 starting new observable
38 Recd A
39 Recd B
40 Recd C
41 Recd D
42
The ExhaustMap receives its values from the srcObservable. For each value, it creates a new observable
i.e. innerObservable. It also automatically subscribes to the innerObservable.
The innerObservable emits the values (A, B, C, D), and pushes it to the subscribers.
The ExhaustMap differs from the MergeMap, SwitchMap & ConcatMap the way it handles the inner
observable. ExhaustMap always waits for the inner observable to finish. It ignores any value it receives
from the source during this period. Any value it receives after the inner observable is finished is accepted
and it creates a new inner observable.
This difference is becomes clear in the next example.
ExhaustMap waits for the inner observable to finish
ExhaustMap creates and waits for inner observable before resuming.
In the following example, we create an observable from the click event of a button using
the fromEvent method. On every click of the button, the ExhaustMap operator returns an inner
observable delayedObs
The delayedObs emits 5 values separated by 1000 ms.
1
2 import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
3 import { of, from, fromEvent, interval, Observable } from 'rxjs';
4 import { switchMap, map, catchError } from 'rxjs/operators';
5
6 @Component({
7 selector: 'app-root',
8 template: `<button #button>Click Me</button>`,
9 })
10 export class AppComponent implements AfterViewInit{
11
12 @ViewChild('button',{static:true}) button;
13 clicks$:Observable<any>;
14
15 ngAfterViewInit() {
16 this.clicks$ = fromEvent(this.button.nativeElement, 'click');
17 this.exhaustMapExample3();
18 }
19
20 delayedObs(count:number) {
21 return new Observable((observer) => {
22 setTimeout(() => { observer.next(count+" A") }, 1000);
23 setTimeout(() => { observer.next(count+" B") }, 2000);
24 setTimeout(() => { observer.next(count+" C") }, 3000);
25 setTimeout(() => { observer.next(count+" D") }, 4000);
26 setTimeout(() => { observer.next(count+" E"); observer.complete() }, 5000);
27 })
28 }
29
30 exhaustMapExample3() {
31
32 let obs=
33
34 this.clicks$
35 .pipe(
36 exhaustMap(() => {
37 this.count=this.count+1;
38 return this.delayedObs(this.count)
39 })
40 )
41 .subscribe(val => console.log(val));
42 }
43
44 }
45
When you click on the button, the clicks observable emits its first value. Inside the exhaustMapwe
increase the count by 1 and pass it to the delayedObs. The exhaustMapsubscribes to the delayedObs.
It starts emitting values A to E prepended by the count.
When you click again, the exhaustMapchecks to see if the previous observable has finished. If not it
ignore the value.
You can verify it from the following result. When we click multiple times, it ignores the values when the
inner observable is running.

Using ExhaustMap in Angular


The exhaustMap is useful in scenarios, where you want to prevent submission of duplicate values
For Example, the user clicking on the Submit button twice will trigger two HTTP calls to the back end.
The ExhaustMap will prevent the creation of new HTTP call until the previous one finishes
Take, TakeUntil, TakeWhile & TakeLast in Angular Observable
1 Comment / March 9, 2023 / 5 minutes of reading
Angular ExhaustMap

Angular Tutorial

First, Last & Single

The take, takeUntil, takeWhile & takeLast operators allow us to filter out the emitted values from the
observable. The take(n) emits the first n values, while takeLast(n) emits the last n values. The
takeUntil(notifier) keeps emitting the values until it is notified to stop. takeWhile(predicate) emits the
value while values satisfy the predicate. All of the stops emitting once done.

Table of Contents
 Take
 TakeUntil
 TakeWhile
o TakeWhile Vs Filter
 TakeLast
 References
Take
Take operator emits the first n number of values before completing. Any reminder values are ignored.
Syntax
take(n)
Where n is the maximum number of values to emit.
If the source emits more than n values, then take emits only n values and completes
If the source emits less than n number of values, then take emits all of them before completing.
Example
app.component.ts
1
2 import { Component, VERSION } from "@angular/core";
3 import { of } from "rxjs";
4 import { take } from "rxjs/operators";
5
6 @Component({
7 selector: "my-app",
8 templateUrl: "./app.component.html",
9 styleUrls: ["./app.component.css"]
10 })
11 export class AppComponent {
12
13 obs = of(1, 2, 3, 4, 5).pipe(take(2));
14
15 ngOnInit() {
16 this.obs.subscribe(val => console.log(val));
17 }
18 }
19
20
21
22 ****Console ******
23 1
24 2
25
Source Code
1
2
3 export class AppComponent {
4
5 takeFive = interval(1000).pipe(take(5));
6
7 ngOnInit() {
8 this.takeFive.subscribe(val => console.log(val));
9 }
10 }
11
12
13 ****Console ******
14 0
15 1
16 2
17 3
18 4
19
TakeUntil
The takeUntil operator returns an Observable that emits value from the source Observable until
the notifier Observable emits a value.
Syntax
1
2 TakeUntil(notifier: Observable): Observable
3
We must pass a notifier observable as the argument to the TakeUntil Operator
TakeUntil emits the values from the Source Observable as long as it does not receive any value from the
notifier observable
When the notifier emits a value, the TakeUntil completes the Source observable.
If the notifier completes without emitting any value, then the TakeUntil keeps emitting values from the
source and completes when the source completes.
Example
In the example below, we create a notifier observable
1
2 notifier= new Subject();
3
The notifier observable emits a value , when use clicks on the stop button.
1
2 stopObs() {
3 this.notifier.next();
4 this.notifier.complete();
5 }
6
Use the takeUntil in the source observable as shown below
1
2 obs = interval(1000).pipe(takeUntil(this.notifier));
3
Run the app. The source observable stops when you click on stop button.
app.component.ts
1
2 import { Component, VERSION } from "@angular/core";
3 import { of, interval, Subject, Observable } from "rxjs";
4 import { take, takeUntil, tap } from "rxjs/operators";
5
6 @Component({
7 selector: "my-app",
8 templateUrl: "./app.component.html",
9 styleUrls: ["./app.component.css"]
10 })
11 export class AppComponent {
12 notifier = new Subject();
13
14 obs = interval(1000).pipe(takeUntil(this.notifier));
15
16 ngOnInit() {
17 this.obs.subscribe(val => console.log(val));
18 }
19
20 stopObs() {
21 this.notifier.next();
22 this.notifier.complete();
23 }
24 }
25
Source Code
app.component.html
1
2 <h1>TakeUntil Example</h1>
3
4 <button (click)="stopObs()">Stop</button>
5 <br>
6
7
Source Code
One of the use cases of takeUntil is to automatically unsubscribe all the observables. You can refer to it
from the tutorial on Unsubscribing from an observable.
TakeWhile
TakeWhile operator will keep emitting the value from the source observable as long as they pass the
given condition (predicate). When it receives a value that does not satisfy the condition it completes the
observable. No further values are emitted even if they satisfy the condition.
Syntax
1
2 takeWhile(predicate: function(value, index): boolean,
3 inclusive?: boolean): Observable
4
Where predicate is the condition.
If inclusive is true, then the emits the value, which does not pass the condition before terminating the
observable.
Example
In the code below takeWhile tests the condition val < 3 against the incoming values. When it receives
the value 3, which does not satisfy the condition, the observable completes. It does not emit any further
values although the stream still has values that satisfy the condition.
1
2 import { Component, VERSION } from "@angular/core";
3 import { of, interval, Subject, Observable } from "rxjs";
4 import { take, takeUntil, takeWhile, tap } from "rxjs/operators";
5
6 @Component({
7 selector: "my-app",
8 templateUrl: "./app.component.html",
9 styleUrls: ["./app.component.css"]
10 })
11 export class AppComponent {
12 obs = of(1, 2, 3, 1, 2, 3, 1, 2, 3)
13 .pipe(
14 takeWhile(val => val < 3)
15 );
16
17 ngOnInit() {
18 this.obs.subscribe(val => console.log(val));
19 }
20 }
21
22
23 *** Console ***
24 1
25 2
26
27
Source Code
With inclusive is set to true, takewhile also emits the value 3 before completing the observable.
1
2 export class AppComponent {
3 obs = of(1, 2, 3, 1, 2, 3, 1, 2, 3)
4 .pipe(
5 takeWhile(val => val < 3, true)
6 );
7
8 ngOnInit() {
9 this.obs.subscribe(val => console.log(val));
10 }
11 }
12
13 *** Console ***
14 1
15 2
16 3
17
Source Code
Example
1
2 evenNumbers = of(2, 4, 6, 3, 8)
3 .pipe(takeWhile(n => n % 2 == 0))
4 .subscribe(val => console.log(val));
5
6 **Console ***
7 2
8 4
9 6
10
11 //8 is not emitted
12
TakeWhile Vs Filter
Both takeWhile & filter uses the condition to filter out the incoming stream. Both allows only the
matching values to pass through discarding the others.
The difference is that takeWhile discards the rest of the stream, when it receives the first value that does
not satisfy the condition (If the inclusive is set to true, then it also emits the last value even when it does
not satisfy the condition). The filter operator never stops the observable.
The following example, filter operator does not stop when it receives the value 3. But it discards it and
continues further until the stream itself completes.
Example
1
2 obs = of(1, 2, 3, 1, 2, 3, 1, 2, 3)
3 .pipe(
4 filter(val => val < 3, true)
5 );
6
7 ngOnInit() {
8 this.obs.subscribe(val => console.log(val));
9 }
10
11
12 ***Console ****
13 1
14 2
15 1
16 2
17 1
18 2
19
Source Code
TakeLast
TakeLast operator emits the last n number of values from the source observable.
Syntax
1
2 takeLast<T>(n: number)
3
Where n is the maximum number of values to emit.
To know the last n number of values, the TakeLast needs to wait for the source to complete. Hence if the
source never completes, then TakeLast will never emit a value.
When the stream completes, the takeLast will
1. emits the last n number of values
2. if the source emits less than the n number of values then it emits all of them
3. stream completes immediatly
Example
1
2 import { Component, VERSION } from "@angular/core";
3 import { of, range, Observable } from "rxjs";
4 import { takeLast } from "rxjs/operators";
5
6 @Component({
7 selector: "my-app",
8 templateUrl: "./app.component.html",
9 styleUrls: ["./app.component.css"]
10 })
11 export class AppComponent {
12 obs = range(1, 100).pipe(takeLast(3));
13
14 ngOnInit() {
15 this.obs.subscribe(val => console.log(val));
16 }
17 }
18
19 ***Console****
20 98
21 99
22 100
23
First, Last & Single Operator in Angular Observable
1 Comment / March 9, 2023 / 5 minutes of reading
Take, TakeUntil, TakeWhile, TakeLast

Angular Tutorial

Skip, SkipUntil, SkipWhile & SkipLast

In the tutorial, let us learn the First, Last & Single RxJs operators in Angular Observable. All three
operators use the predicate (condition) to check the values of the source observable. The first emits the
first matching value, the Last emits the last matching value & the Single emits only if a single value
matches the predicate.

Table of Contents
 First Operator
o First Vs Take(1)
 Last Operator
 Last Vs TakeLast(1)
 Single
 References
First Operator
The first operator emits the first value that meets the condition. If no condition is specified, then it will
emit the first value it receives.
Syntax
1
first<T, D>(predicate?: (value: T, index: number, source: Observable<T>) => boolean, defaultValue?: D)
2
: OperatorFunction<T, T | D>
3

Where
predicate: is the condition to match
defaultValue: is the value to emit if no value matches the condition
1. Emits the first value if no predicate is present
2. Emits the first matching value if the predicate is present
3. Closes the stream after emitting a value
4. If the source completes before emitting any matching value, then it raises the error notification.
Example
In the following example, we create an observable using the of operator. The first operator here emits
the first value it receives i.e 1 and then it completes.
1
2 import { Component, VERSION } from "@angular/core";
3 import { timer, interval, of } from "rxjs";
4 import { first } from "rxjs/operators";
5
6 @Component({
7 selector: "my-app",
8 templateUrl: "./app.component.html",
9 styleUrls: ["./app.component.css"]
10 })
11 export class AppComponent {
12 src = of(1, 2, 3, 4, 5).pipe(first());
13
14 id = Date.now();
15
16 constructor() {}
17
18 ngOnInit() {
19 console.log("Component Created " + this.id);
20
21 this.src.subscribe(value => {
22 console.log(value);
23 });
24 }
25 }
26
27
28 *** Result ****
29 1
30
Source Code
Emits the first value that matches
1
2 src = of(1, 2, 3, 4, 5).pipe(first(val => val > 3));
3
4
5 **Result**
64
7
Source Code
The following code returns an error as no value matches the condition.
1
2 src = of(1, 2, 3, 4, 5).pipe(first(val => val > 10));
3
4
5 ***Error
6 no elements in sequence
7
Source Code
But first with the default value, will emit the default value if no value matches the condition.
1
2 src = of(1, 2, 3, 4, 5).pipe(first(val => val > 10,100));
3
4
5 ***Console**
6 100
7
The following also results in an error, as the source does not emit any values
1
2 src = of().pipe(first());
3
4
5 ***Error
6 no elements in sequence
7
The following emits the default value 100
1
2 src = of().pipe(first(val => true, 100));
3
4
5 ***Console
6 100
7
First Vs Take(1)
The first() (without condition & default value) and take(1) returns the first value they receive from the
source and closes the observable.
But they have a difference in behavior when the source does not emit anything. The first() send an error
notification, while take(1) will not emit anything, but closes the observable.
Last Operator
The last operator emits the last value that meets the condition. If no condition is specified, then it will
emit the last value it receives.
Syntax

1
last<T, D>(predicate?: (value: T, index: number, source: observable<T>) => boolean, defaultValue?: D)
2
:OperatorFunction<T, T | D>
3

1. Waits for the source to complete before emitting the value


2. Emits the last value if no predicate is present
3. Emits the last matching value if the predicate is present
4. Closes the stream after emitting a value
5. If the source completes before emitting any matching value, then It raises the error notification.
Example
In the following example, we create an observable using the of operator. The last operator here emits the
last value it receives i.e 5 and then it completes.
1
2 import { Component, VERSION } from "@angular/core";
3 import { timer, interval, of } from "rxjs";
4 import { last } from "rxjs/operators";
5
6 @Component({
7 selector: "my-app",
8 templateUrl: "./app.component.html",
9 styleUrls: ["./app.component.css"]
10 })
11 export class AppComponent {
12 src = of(1, 2, 3, 4, 5).pipe(last());
13
14 id = Date.now();
15
16 constructor() {}
17
18 ngOnInit() {
19 console.log("Component Created " + this.id);
20
21 this.src.subscribe(value => {
22 console.log(value);
23 });
24 }
25 }
26
27 **Console **
28 5
29
Source Code
Emits the last value that matches the predicate
1
2 src = of(1, 2, 3, 4, 5).pipe(last(val => val < 3));
3
4
5 ***Console**
62
7
Source Code
Returns an error as no value matches the condition.
1
2 src = of(1, 2, 3, 4, 5).pipe(last(val => val < 0));
3
4
5 *** Console *****
6 ERROR
7 Error: no elements in sequence
8
9
But with a default value, it will emit the default value if no value matches the condition.
1
2 src = of(1, 2, 3, 4, 5).pipe(last(val => val < 0,0));
3
4
5 ***Console**
6 100
7
The following also results in an error, as the source does not emit any values
1
2 src = of().pipe(last());
3
4 ***Error
5 no elements in sequence
6
The following emits the default value 100
1
2 src = of().pipe(last(val => true, 100));
3
4
5 ***Console
6 100
7
Last Vs TakeLast(1)
The last() (without condition & default value) and takeLast(1) returns the last value they receive from the
source observable.
But they have a difference in behavior when the source does not emit anything. The last() send an error
notification, while takeLast(1) will not emit anything, but closes the observable.
Single
The Single operator emits a single value that meets the condition.
1. The Single operator waits for the source to complete before emitting the value
2. Emits a single value that meets the condition
3. If more than one value satisfies the condition, then it raises an error notification
4. If no value satisfies the condition, then it emits the value undefined
5. Raises the error notification, if the source does not emit any value.
Syntax

1
single<T>(predicate?: (value: T, index: number, source: Observable<T>) => boolean):
2
MonoTypeOperatorFunction<T>
3

Where
predicate is the condition
Examples
Emits 3 as it matches the condition.
1
2 src = of(1, 2, 3, 4, 5).pipe(single(val => val == 3));
3
4
5 **Console
63
7
Source Code
Waits for the observable to finish. Hence the following will never emit a value.
1
2 src = interval(1000).pipe(single(val => val == 3));
3
4 **Console*
5
Raises error notification as there are more than one value that satisfies the condition.
1
2 src = of(1, 2, 3, 4, 3).pipe(single(val => val == 3));
3
4
5 **Console**
6 ERROR
7 Sequence contains more than one element
8
9
If the source does not emit any matching values, then the Single operator emits undefined. Note that it
does not emit error notification.
1
2 src = of(1, 2, 3, 4, 3).pipe(single(val => val == 5));
3
4 *Console*
5 undefined
6
Single without any predicate matches all values. Hence the error.
1
2 src = of(1, 2, 3, 4, 3).pipe(single());
3
4 ***Console***
5 ERROR
6 Sequence contains more than one element
7
Source contains single value and Single without predicate. Emits the value
1
2 src = of(1).pipe(single());
3
4 **Console**
51
6
Source is empty, Hence it raises error notification.
1
2 src = of().pipe(single());
3
4
5 **Console***
6 ERROR
7 Error: no elements in sequence
8
The Scan & Reduce operators in Angular
Leave a Comment / March 9, 2023 / 5 minutes of reading
Skip, SkipUntil, SkipWhile & SkipLast

Angular Tutorial

Debounce & DebounceTime

The Scan & Reduce Operators in Angular applies an accumulator function on the values of the source
observable. The Scan Operator returns all intermediate results of the accumulation, while Reduce only
emits the last result. Both also use an optional seed value as the initial value.

00:00/00:00
Table of Contents
Scan in Angular
The scan operator applies an accumulator function over the values emitted by the source Observableble
sequentially and emits each value.
Syntax
1
2 scan<T, R>(accumulator: (acc: R, value: T, index: number) => R, seed?: T | R): OperatorFunction<T, R>
3
Where
 accumulator is the function, that is called on each source value
 seed is the initial accumulation value (optional)
The accumulator function gets three argument.
acc is the accumulator variable where the values are accumulated.
value comes from the source observable,
index of the value.
The initial value for the acc comes from the seed.
When the first value arrives from the source, the scan operator invokes the accumulator function on
these two variables and emits the result.
When the second value arrives from the source, the result of the previous step becomes the input ( acc ).
The scan emits a new result, which then becomes the input for the third emission.
This cycle continues till the stream completes.
Scan Example
In the example below (acc, value) => acc + value is the accumulator function. Seed is 0.
1
2 import { Component } from "@angular/core";
3 import { map, scan } from "rxjs/operators";
4 import { interval, of } from "rxjs";
5
6 @Component({
7 selector: "my-app",
8 template: `
9 <h1>Scan Operator Example</h1>
10 `,
11 styleUrls: ["./app.component.css"]
12 })
13 export class AppComponent {
14 reTryCount = 0;
15
16 ngOnInit() {
17 of(1, 2, 3, 4, 5)
18 .pipe(scan((acc, value) => acc + value, 0))
19 .subscribe(
20 val => console.log(val),
21 e => console.log(e),
22 () => console.log("Complete")
23 );
24 }
25 }
26
27
28 ***Console***
29
30 1
31 3
32 6
33 10
34 15
35 Complete
36
Source Code
The value for acc starts with the seed value i.e. 0. The variable value gets the value 1, which is the first
value emitted by the source. The scan operator runs the accumulator function (acc + value = 1) and
emits the result.
The result of the previous accumulator function becomes the input (acc) of the next scan. It is added to
the next value (i. e. 2) emitted from the source and the result becomes 3.
This will continue until we reach the end of sequence
In the following code, we change the seed to 10. Now the accumulator starts with 10 instead of 0.
1
2 of(1, 2, 3, 4, 5)
3 .pipe(scan((acc, value) => acc + value, 10))
4 .subscribe(
5 val => console.log(val),
6 e => console.log(e),
7 () => console.log("Complete")
8 );
9
10 *** Result ***
11 11
12 13
13 16
14 20
15 25
16 Complete
17
18
Combining as Arrays
1
2 of(1, 2, 3, 4, 5)
3 .pipe(scan((acc, value) => [...acc, value], []))
4 .subscribe(
5 val => console.log(val),
6 e => console.log(e),
7 () => console.log("Complete")
8 );
9
10 *** Console ***
11 [1]
12 [1, 2]
13 [1, 2, 3]
14 [1, 2, 3, 4]
15 [1, 2, 3, 4, 5]
16
Source Code
Tracking Button Clicks
1
2 import { Component, ElementRef, ViewChild } from "@angular/core";
3 import { map, scan } from "rxjs/operators";
4 import { fromEvent, interval, of, Subscription } from "rxjs";
5
6 @Component({
7 selector: "my-app",
8 template: `
9 <h1>Scan Operator Example</h1>
10
11 <button #btn>Button</button>
12 `,
13 styleUrls: ["./app.component.css"]
14 })
15 export class AppComponent {
16 @ViewChild("btn", { static: true }) button: ElementRef;
17 sub: Subscription;
18
19 ngAfterViewInit() {
20 this.sub = fromEvent(this.button.nativeElement, "click")
21 .pipe(scan((acc, value) => acc + 1, 0))
22 .subscribe(val => console.log("You clicked " + val + " times"));
23 }
24
25 ngOnDestroy() {
26 this.sub.unsubscribe();
27 }
28 }
29
30
Source Code
Reduce in Angular
The Reduce operator applies an accumulator function over the values emitted by the source
Observation sequentially and returns the accumulated result when the source completes.
The Reduce operator behaves exactly like the scan operator, except for the following differences
1. It does not return the intermediate results.
2. It returns only after the source completes.
Reduce Example
The following example is similar to the scan example above. The only difference is that you will not see
the intermediate results i.e. 1, 3, 6 10.
1
2 ngOnInit() {
3 of(1, 2, 3, 4, 5)
4 .pipe(reduce((acc, value) => acc + value, 0))
5 .subscribe(
6 val => console.log(val),
7 e => console.log(e),
8 () => console.log("Complete")
9 );
10 }
11
12
13 ** Console **
14
15 15
16 Complete
17
Source Code
Combining as Arrays
1
2 ngOnInit() {
3 of(1, 2, 3, 4, 5)
4 .pipe(reduce((acc, value) => [...acc, value], []))
5 .subscribe(
6 val => console.log(val),
7 e => console.log(e),
8 () => console.log("Complete")
9 );
10 }
11
12 ** Console ***
13 [1, 2, 3, 4, 5]
14 Complete
15
Source Code
Tracking Button Clicks
The Reduce operator emits only if the observable completes. Hence in the Tracking button click
example, just replacing the scan with the reduce will not work.
In the following example, we create a new observable using the Subject and emit the click event using
the event binding. This allows us to raise the complete notification.
1
2 import { Component, ElementRef, ViewChild } from "@angular/core";
3 import { map, reduce, scan } from "rxjs/operators";
4 import { fromEvent, interval, of, Subject, Subscription } from "rxjs";
5
6 @Component({
7 selector: "my-app",
8 template: `
9 <h1>Reduce Operator Example</h1>
10
11 <button (click)="clickMe($event)">Click Me</button>
12 <br />
13 <br />
14 <br />
15 <button (click)="startCounting($event)">Sart</button>
16
17 <button (click)="stopCounting()">Stop</button>
18 `,
19 styleUrls: ["./app.component.css"]
20 })
21 export class AppComponent {
22 clickStream: Subject<Event>;
23 sub: Subscription;
24
25 ngOnInit() {}
26
27 clickMe(event: Event) {
28 console.log("Clicked");
29 if (this.clickStream) this.clickStream.next(event);
30 }
31
32 startCounting(event: Event) {
33 this.clickStream = new Subject<Event>();
34 this.sub = this.clickStream
35 .asObservable()
36 .pipe(reduce((acc, value) => acc + 1, 0))
37 .subscribe(val => console.log("You clicked " + val + " times"));
38 }
39
40 stopCounting() {
41 this.clickStream.complete();
42 }
43
44 ngOnDestroy() {}
45 }
46
47
DebounceTime & Debounce in Angular
Leave a Comment / March 9, 2023 / 3 minutes of reading
Scan & Reduce

Angular Tutorial

Delay & DelayWhen

DebounceTime & Debounce are the Angular RxJs Operators. Both emit values from the source
observable, only after a certain amount of time has elapsed since the last value. Both emit only the latest
value and discard any intermediate values. In this tutorial, we will learn how to use both DebounceTime
& Debounce with examples.

Table of Contents
 Use Case of Debounce Operators
 DebounceTime
o How it works
o DebounceTime Example
o Sending HTTP GET Request
 Debounce
o Debounce Example
 Reference
Use Case of Debounce Operators
The typeahead/autocomplete fields are one of the most common use cases for Debounce Operators.
As the user types in the typeahead field, we need to listen to it and send an HTTP request to the back end
to get a list of possible values. If we send HTTP requests for every keystroke, we end up making
numerous unneeded calls to the server.
By using the Debounce Operators, we wait until the user pauses typing before sending an HTTP Request.
This will eliminates unnecessary HTTP requests.
DebounceTime
The Debouncetime emits the last received value from the source observable after a specified amount of
time has elapsed without any other value appearing on the source Observable
Syntax

1
debounceTime<T>(dueTime: number, scheduler: SchedulerLike = async):
2
MonoTypeOperatorFunction<T>
3

Where dueTime The timeout duration in milliseconds.


How it works
 First, we assign a timeout duration (dueTime) to the Debouncetime operator.
 The Debouncetime operator starts counting time after it receives a value.
 If the source observable emits a value before the timeout duration, then counting is reset to zero
& started again.
 When the timeout duration elapses the operator emits the last value and the counting stops.
 Counting starts again when the operators receive another value.
DebounceTime Example
The following DebounceTime example shows how to use the operator to listen for input field changes
1
2 import { Component, VERSION } from "@angular/core";
3 import { FormControl, FormGroup } from "@angular/forms";
4 import { Observable, Subscription } from "rxjs";
5 import { debounceTime } from "rxjs/operators";
6
7 @Component({
8 selector: "my-app",
9 template: `
10 <form [formGroup]="mform">Name: <input formControlName="name" /></form>
11 `,
12 styleUrls: ["./app.component.css"]
13 })
14 export class AppComponent {
15
16 mform: FormGroup = new FormGroup({
17 name: new FormControl()
18 });
19
20 obs:Subscription;
21
22 ngOnInit() {
23 this.obs=this.mform.valueChanges
24 .pipe(debounceTime(500))
25 .subscribe(data => console.log(data));
26 }
27
28 ngOnDestroy() {
29 this.obs.unsubscribe();
30 }
31 }
32
Souce Code
Sending HTTP GET Request
The following example shows how you can send an HTTP GET Request using switchMap &
debounceTime.
1
2 ngOnInit() {
3 this.obs=this.mform.valueChanges
4 .pipe(
5 debounceTime(500),
6 switchMap(id => {
7
8 console.log(id)
9 return this.http.get(url)
10
11 })
12 )
13 .subscribe(data => console.log(data));
14 }
15
Debounce
The Debounce operator is similar to the DebounceTime operator, but another observable will provide
the time span. By Using the Debounce, we can set the time span dynamically.
Debounce Example
The following example works the same as the previous example. Instead of using the hardcoded time
span, we create a new observable using the interval operator.
1
2 import { Component, VERSION } from "@angular/core";
3 import { FormControl, FormGroup } from "@angular/forms";
4 import { debounce } from "rxjs/operators";
5 import { interval, Subscription } from "rxjs";
6
7 @Component({
8 selector: "my-app",
9 template: `
10 <form [formGroup]="mform">Name: <input formControlName="name" /></form>
11 `,
12 styleUrls: ["./app.component.css"]
13 })
14 export class AppComponent {
15 mform: FormGroup = new FormGroup({
16 name: new FormControl()
17 });
18
19 obs:Subscription
20
21 ngOnInit() {
22 this.obs=this.mform.valueChanges
23 .pipe(debounce(() => interval(500)))
24 .subscribe(data => console.log(data));
25 }
26
27 ngOnDestroy() {
28 this.obs.unsubscribe()
29 }
30
31 }
32
33
Source Code
You can also customize the delay. In the following example, we increase the delay by 100ms after every
keystroke.
1
2 delay = 500;
3
4 obs: Subscription;
5
6 ngOnInit() {
7 this.obs = this.mform.valueChanges
8 .pipe(
9 debounce(() => {
10 this.delay = this.delay + 100;
11 console.log(this.delay);
12 return interval(this.delay);
13 })
14 )
15
.subscribe(data => console.log(data));
16
}
17
Delay & DelayWhen in Angular
Leave a Comment / March 9, 2023 / 3 minutes of reading
DebounceTime & Debounce

Angular Tutorial

ThrowError

Delay & DelayWhen Operators in Angular delays the emission of values from the source observable. The
Delay operator delays by a given timeout or until a given Date. The DelayWhen delays until it receives a
notification from another observable.

Table of Contents
 Delay
o Delay Example
o Delay Each item
o Passing Date to Delay Operator
 DelayWhen
o DelayWhen Example
 References
Delay
Delays the emission of items from the source Observable by a given timeout or until a given Date.
Syntax
1
2 delay<T>(delay: number | Date, scheduler: SchedulerLike = async): MonoTypeOperatorFunction<T>
3
Where
delay is the delay in milliseconds or a Date until which the emission of the source items are delayed
Note that delay delays the entire observable and not the individual items.
Delay Example
In the following example, we add a delay of 1000ms. After 1000ms all the values appear instantly.
1
2 import { Component, VERSION } from "@angular/core";
3 import { of } from "rxjs";
4 import { delay, map, tap } from "rxjs/operators";
5
6 @Component({
7 selector: "my-app",
8 template: `
9 <h1>Delay & DelayWhen Example</h1>
10 `,
11 styleUrls: ["./app.component.css"]
12 })
13 export class AppComponent {
14 ngOnInit() {
15 of(1, 2, 3, 4, 5)
16 .pipe(
17 tap(val => console.log("Before " + val)),
18 delay(1000)
19 )
20 .subscribe(
21 val => console.log(val),
22 e => console.log(e),
23 () => console.log("Complete")
24 );
25 }
26 }
27
28
29 Before 1
30 Before 2
31 Before 3
32 Before 4
33 Before 5
34
35 1
36 //Appears after a delay of 1000ms
37 2
38 3
39 4
40 5
41 Complete
42
Source Code
Delay Each item
The following code uses concatMap with delay operator to add delay between each emission.
1
2
3 of(1, 2, 3, 4, 5)
4 .pipe(
5 tap(val => console.log("Before " + val)),
6 concatMap(item => of(item).pipe(delay(1000)))
7 )
8 .subscribe(
9 val => console.log(val),
10 e => console.log(e),
11 () => console.log("Complete")
12 );
13
14
15 *** Console ****
16
17 Before 1
18 Before 2
19 Before 3
20 Before 4
21 Before 5
22
23 1
24 2
25 3
26 4
27 5
28 Complete
29
Source Code
Passing Date to Delay Operator
Instead of delay in milliseconds, we can also pass the date. Operator time shifts the start of the
Observable execution until the given date occurs.
In the following example, we add a 5 second to the current date and pass it to the delay operator.
1
2 import { Component, VERSION } from "@angular/core";
3 import { of } from "rxjs";
4 import { delay, tap } from "rxjs/operators";
5
6 @Component({
7 selector: "my-app",
8 template: `
9 <h1>Delay & DelayWhen Example</h1>
10 `,
11 styleUrls: ["./app.component.css"]
12 })
13 export class AppComponent {
14 dt = new Date();
15
16 ngOnInit() {
17 console.log(this.dt);
18
19 this.dt.setSeconds(this.dt.getSeconds() + 5);
20 console.log(this.dt);
21
22 of(1, 2, 3, 4, 5)
23 .pipe(
24 tap(val => console.log("Tap " + val)),
25 delay(this.dt)
26 )
27 .subscribe(
28 val => console.log(val),
29 e => console.log(e),
30 () => console.log("Complete")
31 );
32 }
33 }
34
35
36
Source Code
DelayWhen
Delays the emission of items from the source observable by a given time span determined by the
emissions of another observable.
DelayWhen Example
The DelayWhen triggers when the timer observable emits an value after 1000 ms.
1
2 of(1, 2, 3, 4, 5)
3 .pipe(
4 tap(val => console.log("Before " + val)),
5 delayWhen(() => timer(1000))
6 )
7 .subscribe(
8 val => console.log(val),
9 e => console.log(e),
10 () => console.log("Complete")
11 );
12
13
14 *** Console ****
15 Before 1
16 Before 2
17 Before 3
18 Before 4
19 Before 5
20 1
21 2
22 3
23 4
24 5
25 Complete
26
In the following example, we create notification observable using Subject and use it in the DelayWhen
Operator. We emit the notification when the users click on a button. The DelayWhen waits until the
notification before emitting the values
1
2 import { Component, VERSION } from "@angular/core";
3 import { interval, of, Subject, timer } from "rxjs";
4 import { concatMap, delay, delayWhen, map, tap } from "rxjs/operators";
5
6 @Component({
7 selector: "my-app",
8 template: `
9 <h1>Delay & DelayWhen Example</h1>
10
11 <button (click)="emit()">Emit</button>
12 `,
13 styleUrls: ["./app.component.css"]
14 })
15 export class AppComponent {
16 click$ = new Subject<Event>();
17
18 ngOnInit() {
19 of(1, 2, 3, 4, 5)
20 .pipe(
21 tap(val => console.log("Before " + val)),
22 delayWhen(() => this.click$.asObservable())
23 )
24 .subscribe(
25 val => console.log(val),
26 e => console.log(e),
27 () => console.log("Complete")
28 );
29 }
30
31 emit() {
32 this.click$.next();
33 }
34
35 }
36
37
Source Code
References
Using ThrowError in Angular Observable
Leave a Comment / March 9, 2023 / 6 minutes of reading
Delay & DelayWhen

Angular Tutorial

CatchError

Angular ThrowError operator returns an observable, which on subscription immediately errors out. It
does not emit any results.

Table of Contents
 ThrowError
 Throw Error Vs ThrowError
o Throw Error Example
o ThrowError
 Using ThrowError
o Using with catchError
o Using it with MergeMap
 References
ThrowError
ThrowError creates a new observable. Hence we must subscribe to it. The following example creates an
ThrowError observable and then subscribes to it.
1
2 import { Component, VERSION } from "@angular/core";
3 import { Observable, of, from, throwError } from "rxjs";
4 import { map, catchError } from "rxjs/operators";
5
6 @Component({
7 selector: "my-app",
8 templateUrl: "./app.component.html",
9 styleUrls: ["./app.component.css"]
10 })
11 export class AppComponent {
12 name = "Angular " + VERSION.major;
13
14 obs = throwError("Error From ThrowError observable");
15
16 ngOnInit() {
17 this.obs.subscribe(
18 el => {
19 console.log("Value Received :" + el);
20 },
21 err => {
22 console.log("Error caught at Subscriber :" + err);
23 },
24 () => console.log("Processing Complete")
25 );
26 }
27 }
28
29
30
31 ****Console Window
32
33 Error caught at Subscriber: Error From ThrowError observable
34
Source Code
First, we create an observable using throwError. The first argument to the throwError is the error object.
This error object is passed to the consumers when it raises the error notification.
1
2 obs = throwError("Error From ThrowError observable")
3
We, subscribe to it in the ngOnInit method.
1
2 this.obs.subscribe(
3
4
The observable immediately raises the error notification and completes. The error callback is invoked
and we will see the error message in the console window.
1
2 err => {
3 console.log("Error caught at Subscriber :" + err);
4 },
5
6
Throw Error Vs ThrowError
It is very easy confuse between the Throw Error With ThrowError.
Throw Error throws an error. It is a JavaScript construct and is not part of the RxJs. We need to use the
try/catch block to catch the errors thrown from the Throw Error. The RxJS uses the try/catch block to
catch any errors thrown from the observables. And when they catch one, they emit an error
notification (raises the error callback), and then the observable stops.
ThrowError does not throw errors like throw Error. It returns a new observable, which emit an error
notification (raises the error callback), and then stops.
Throw Error Example
1
2 import { Component, VERSION } from "@angular/core";
3 import { Observable, of, from, throwError } from "rxjs";
4 import { map, catchError } from "rxjs/operators";
5
6 @Component({
7 selector: "my-app",
8 templateUrl: "./app.component.html",
9 styleUrls: ["./app.component.css"]
10 })
11 export class AppComponent {
12
13
14 srcArray = from([1, 2, "A", 4]);
15
16 obs = this.srcArray.pipe(
17 map(val => {
18 let result = (val as number) * 2;
19 if (Number.isNaN(result)) {
20 console.log("Error in the observable");
21 throw Error("Not a Number");
22 }
23 return result;
24 })
25 );
26
27 ngOnInit() {
28 this.obs.subscribe(
29 el => {
30 console.log("Value Received :" + el);
31 },
32 err => {
33 console.log("Error caught at Subscriber :" + err);
34 },
35 () => console.log("Processing Complete.")
36 );
37 }
38 }
39
40
41 ***Console ****
42
43 Value Received :2
44 Value Received :4
45 Error in the observable
46 Error caught at Subscriber :Error: Not a Number
47
Source Code
The observable emits values 2 & 4.
When map operators receive the value A it uses throw Error to throw an error. The observable catches
this error and raises the error notification and terminates.
The last value 8 is never emitted.
ThrowError
Now, let us replace the throw Error with return throwError
1
2 import { Component, VERSION } from "@angular/core";
3 import { Observable, of, from, throwError } from "rxjs";
4 import { map, catchError } from "rxjs/operators";
5
6 @Component({
7 selector: "my-app",
8 templateUrl: "./app.component.html",
9 styleUrls: ["./app.component.css"]
10 })
11 export class AppComponent {
12 name = "Angular " + VERSION.major;
13
14 srcArray = from([1, 2, "A", 4]);
15
16 obs = this.srcArray.pipe(
17 map(val => {
18 let result = (val as number) * 2;
19 if (Number.isNaN(result)) {
20 console.log("Error in the observable");
21 return throwError("Not a Number");
22 }
23 return result;
24 })
25 );
26
27 ngOnInit() {
28 this.obs.subscribe(
29 (el: any) => {
30 console.log("Value Received :" + el);
31 },
32 err => {
33 console.log("Error caught at Subscriber :" + err);
34 },
35 () => console.log("Processing Complete.")
36 );
37 }
38 }
39
40
41 ****Console ********
42 Value Received :2
43 Value Received :4
44 Error in the observable
45 Value Received :[object Object]
46 Value Received :8
47 Processing Complete
48
49
Source Code
The observable emits values 2 & 4.
When the map operator receive the value A it returns throwError. Remember throwError returns an
observable. It will raise the error notification, only if you subscribe to it.
The map operator does not subscribe to the observable. It just returns it to the subscriber.
Hence the subscriber receives the throwError observable as value. Hence you see [object Object] in the
console.
Since there is no error raised, the observable continues and emits the next value 8 and then completes.
Using ThrowError
The throwError needs to be subscribed for it to emit error notification. We can use it to compose with
other Observables such as mergeMap, switchMap, catchError etc.
Using with catchError
The following example, shows how to use ThrowError with CatchError
1
2 import { Component, OnInit } from "@angular/core";
3 import { throwError, from } from "rxjs";
4 import { map, catchError } from "rxjs/operators";
5
6 @Component({
7 selector: "my-app",
8 templateUrl: "./app.component.html",
9 styleUrls: ["./app.component.css"]
10 })
11 export class AppComponent {
12 srcArray = from([1, 2, "A", 4]);
13
14 obs = this.srcArray.pipe(
15 map(val => {
16 let result = (val as number) * 2;
17 if (Number.isNaN(result)) {
18 console.log("Errors Occurred in Stream");
19 throw new Error("Result is NaN");
20 }
21 return result;
22 }),
23 catchError(error => {
24 console.log("Caught in CatchError. Throwing error");
25 return throwError(error);
26 })
27 );
28
29 ngOnInit() {
30 this.obs.subscribe(
31 el => {
32 console.log("Value Received " + el);
33 },
34 err => {
35 console.log("Error caught at Subscriber " + err);
36 },
37 () => console.log("Processing Complete.")
38 );
39 }
40 }
41
42
43 ******* CONSOLE *******
44 Value Received 2
45 Value Received 4
46 Errors Occurred in Stream
47 Caught in CatchError. Throwing error
48 Error caught at Subscriber Error: Result is NaN
49
50
Source Code
The code throws the error using throw error in map operator.
CatchError will catch this error. We use the CatchError to handle the errors thrown by the Angular
Observable. Once we handle the error, we must return an observable. We can either return a
replacement observable or return an error. The observable returned from CatchError is immediately
subscribed.
Hence we can use the throwError here, which is immediately subscribed , which in turn emits an error
notification
1
2 catchError(error => {
3 console.log("Caught in CatchError. Throwing error");
4 return throwError(error);
5 })
6
7
Using it with MergeMap
The Angular MergeMap maps each value from the source observable into an inner observable,
subscribes to it, and then starts emitting the values from it.
In the following example, we use throwError to return a observable, when we receive the value 3.
The MergeMap subscribes to this new observable and raises the error notification and stops.
1
2 import { Component, OnInit } from "@angular/core";
3 import { throwError, of } from "rxjs";
4 import { map, mergeMap, catchError } from "rxjs/operators";
5
6 @Component({
7 selector: "my-app",
8 templateUrl: "./app.component.html",
9 styleUrls: ["./app.component.css"]
10 })
11 export class AppComponent {
12 srcObservable = of(1, 2, 3, 4);
13 innerObservable = of("A", "B");
14
15 obs = this.srcObservable.pipe(
16 mergeMap(val => {
17 console.log("Source value " + val);
18 console.log("starting new observable");
19
20 if (val == 3) return throwError("Error in observable");
21
22
23 return this.innerObservable;
24 })
25 );
26
27 ngOnInit() {
28 this.obs.subscribe(
29 el => {
30 console.log("Value Received " + el);
31 },
32 err => {
33 console.log("Error caught at Subscriber " + err);
34 },
35 () => console.log("Processing Complete.")
36 );
37 }
38 }
39
40
41 ***Console ****
42 Source value 1
43 starting new observable
44 Value Received A
45 Value Received B
46 Source value 2
47 starting new observable
48 Value Received A
49 Value Received B
50 Source value 3
51 starting new observable
52 Error caught at Subscriber Error in observable
53
Using Catcherror Operator in Angular Observable
1 Comment / March 9, 2023 / 6 minutes of reading
ThrowError

Angular Tutorial

ReTry & ReTryWhen

Angular CatchError is an RxJs Operator. We can use it to handle the errors thrown by the Angular
Observable. Like all other RxJs operators, the CatchError also takes an observable as input and returns
an observable (or throws an error). We can use CatchError to provide a replacement observable or throw
a user-defined error. Let us learn all these in this tutorial.

Catch operator was renamed as catchError in RxJs 5.5, Hence if you are using Angular 5 or prior version
then use catch instead of catchError.
Table of Contents
 Handling Errors in Observable
o Using Error Callback of Subscribe method
o Catch errors in the observable stream
 Using CatchError Operator
o Syntax
o Returning a new observable
o Throws a new Error
o Retrying
 References
Handling Errors in Observable
We can handle the errors at two places.
1. Using the error callback of the subscribe method
2. Catch errors in the observable stream
Using Error Callback of Subscribe method
We subscribe to an Observable by using the subscribe method. The subscribe method accepts three
callback methods as arguments. They are the next value, error, or complete event. We use the error
callback to catch & handle the errors.
For Example, consider the following code. The obs observable multiplies the values (srcArray) by 2 using
the map operator. If the result is NaN, then we throw an error using throw new Error("Result is NaN").

BEST ANGULAR BOOKS


The Top 8 Best Angular Books, which helps you to get started with Angular
1
2 srcArray = from([1, 2, 'A', 4]);
3
4 obs = this.srcArray
5 .pipe(
6 map(val => {
7 let result = val as number * 2;
8 if (Number.isNaN(result)) {
9 console.log('Errors Occurred in Stream')
10 throw new Error("Result is NaN")
11 }
12 return result
13 }),
14 );
15
16 ngOnInit() {
17
18 this.obs.subscribe(
19 el => {
20 console.log('Value Received ' + el)
21 },
22 err => {
23 console.log("Error caught at Subscriber " + err)
24 },
25 () => console.log("Processing Complete.")
26 )
27 }
28
29
30 **** Output *****
31 Value Received 2
32 Value Received 4
33 Errors Occurred in Stream
34 Error Caught at subscriber Error: Result is NaN
35
Source Code
We subscribe and start to receive the values from the obs observable in the ngOnInit method. When the
observable stream throws an error, it invokes the error callback. In the error callback, we decide what to
do with the error.
Note that once the observable errors out it will not emit any values neither it calls
the complete callback. Our subscription method will never receive the final value of 8.
Catch errors in the observable stream
Another option to catch errors is to use the CatchError Operator. The CatchError Operators catches the
error in the observable stream as and when the error happens. This allows us to retry the failed
observable or use a replacement observable.
Using CatchError Operator
To use CatchError operator, we need to import it from the rxjs/operators as shown below
1
2 import { catchError } from 'rxjs/operators'
3
Syntax
The catchError is a pipeable operator. We can use it in a Pipe method similar to the other operators
like Map, etc.
The catchError operator gets two argument.
The first argument is err, which is the error object that was caught.
The second argument is caught, which is the source observable. We can return it back effectively
retrying the observable.
The catchError must return a new observable or it can throw an error.
Returning a new observable
The following examples shows the use of catchError operator.
1
2 srcArray = from([1, 2, 'A', 4]);
3
4 obs = this.srcArray
5 .pipe(
6 map(val => {
7 let result = val as number * 2;
8 if (Number.isNaN(result)) {
9 console.log('Errors Occurred in Stream')
10 throw new Error("Result is NaN")
11 }
12 return result
13 }),
14 catchError(error => {
15 console.log('Caught in CatchError. Returning 0')
16 return of(0); //return from(['A','B','C'])
17 })
18 );
19
20
21 //Output
22 Value Received 2
23 Value Received 4
24 Errors Occurred in Stream
25 Caught in CatchError. Returning 0
26 Value Received 0
27 Observable Completed
28
Source Code
In the code above, the map emits the values 2 & 4, which is input to the catchError. Since there are no
errors, catchError forwards it to the output. Hence the subscribers receive values 2 & 4.
The catchError comes into play, when the map operator throws an error. The catchError handle the
error and must return a new observable (or throw an error). In the example above we return a new
observable i.e. of(0). You can also emit any observable for example return from(['A','B','C']) etc
You can also return the original observable. Just use the return this.obs; instead of return of(0);.
But beware, It will result in an infinite loop.
The new observable is automatically subscribed and the subscriber gets the value 0. The new observable
now finishes and emits the complete event.
Since the original observable ended in a error, it will never emit the the value 8.
Throws a new Error
catchError can also throw an error. In the following example, we use the throw new Error(error) to
throw a JavaScript error. This error will propagate to the subscriber as shown in the example below.
1
2 obs = this.srcArray
3 .pipe(
4 map(val => {
5 let result = val as number * 2;
6 if (Number.isNaN(result)) {
7 console.log('Errors Occurred in Stream')
8 throw new Error("Result is NaN")
9 }
10 return result
11 }),
12 catchError(error => {
13 console.log('Caught in CatchError. Throwing error')
14 throw new Error(error)
15 })
16 );
17
18
19 //OUTPUT
20 Value Received 2
21 Value Received 4
22 Errors Occurred in Stream
23 Caught in CatchError. Throwing error
24 Error caught at Subscriber Error: Error: Result is NaN
25
Source Code
We can also make use of throwError to return an observable. Remember that the throwError does not
throw an error like throw new Error but returns an observable, which emits an error immediately.
1
2 obs = this.srcArray
3 .pipe(
4 map(val => {
5 let result = val as number * 2;
6 if (Number.isNaN(result)) {
7 console.log('Errors Occurred in Stream')
8 throw new Error("Result is NaN")
9 }
10 return result
11 }),
12 catchError(error => {
13 console.log('Caught in CatchError. Throwing error')
14 return throwError(error);
15 })
16 );
17
18 //OUTPUT
19 Value Received 2
20 Value Received 4
21 Errors Occurred in Stream
22 Caught in CatchError. Throwing error
23 Error caught at Subscriber Error: Result is NaN
24
Source code
Retrying
You can also retry the observable using the Retry operator.
1
2 obs = this.srcArray
3 .pipe(
4 map(val => {
5 let result = val as number * 2;
6 if (Number.isNaN(result)) {
7 console.log('Errors Occurred in Stream')
8 throw new Error("Result is NaN")
9 }
10 return result
11 }),
12 retry(2),
13 catchError((error,src) => {
14 console.log('Caught in CatchError. Throwing error')
15 throw new Error(error)
16 })
17 );
18
19
20 //Output
21 Value Received 2
22 Value Received 4
23 Errors Occurred in Stream
24 Value Received 2
25 Value Received 4
26 Errors Occurred in Stream
27 Value Received 2
28 Value Received 4
29 Errors Occurred in Stream
30 Caught in CatchError. Throwing error
31 Error caught at Subscriber Error: Error: Result is NaN
32
Source Code
The catchError gets the source observable as the second argument. If we return it, it will get subscribed
again effectively retrying the observable.
Ensure that you keep track of no of tries so that you can stop the observable after a few failed attempts.
Otherwise, you may run into an infinite loop if the observable always emits an error.
1
2 obs = this.srcArray
3 .pipe(
4 map(val => {
5 let result = val as number * 2;
6 if (Number.isNaN(result)) {
7 console.log('Errors Occurred in Stream')
8 throw new Error("Result is NaN")
9 }
10 return result
11 }),
12 catchError((error,src) => {
13 console.log('Caught in CatchError. Throwing error')
14 this.count++;
15 if (this.count < 2) {
16 return src;
17 } else {
18 throw new Error(error)
19 }
20
})
21
);
22
ReTry, ReTryWhen in Angular Observable
1 Comment / March 9, 2023 / 6 minutes of reading
CatchError

Angular Tutorial

Unsubscribe Angular

ReTry & ReTryWhen Operators help us to retry a failed observable in Angular. These operators are useful
in Error handling. They both resubscribe to the source observable when they
receive onError() notification.

Table of Contents
 ReTry
o ReTry Example
 ReTryWhen
o How it works
o ReTryWhen Example
o Adding a Delay
o Notifier observable
o Limiting Retry Attempts
 References
ReTry
The ReTry Angule RxJs operator retries a failed source observable count number of times. If the count is
not provided then it tries indefinitely
Syntax
1
2 retry<T>(count: number = -1): MonoTypeOperatorFunction<T>
3
Mirrors the source observable, if there are no errors.
If the source observable calls error notification, it does not propagate it. But re subscribes to the source
again for a maximum of count times.
The Retry operator retries the operation immediately
ReTry Example
In the example below, map operator throws an error if the source emits a value greater than 3.
The ReTry(2) retries the operation twice before erroring out.
1
2 import { Component } from "@angular/core";
3 import { map, retry, tap } from "rxjs/operators";
4 import { interval } from "rxjs";
5
6 @Component({
7 selector: "my-app",
8 template: `
9 <h1>Retry And ReTryWhen Example</h1>
10 `,
11 styleUrls: ["./app.component.css"]
12 })
13 export class AppComponent {
14 ngOnInit() {
15 interval(1000)
16 .pipe(
17 map(val => {
18 if (val > 2) throw new Error("Invalid Value");
19 return val;
20 }),
21 retry(2)
22 )
23 .subscribe(
24 val => console.log(val),
25 err => console.log(err),
26 () => console.log("Complete")
27 );
28 }
29 }
30
31
Source Code
Retry without any argument, will retry indefinitely
1
2 interval(1000)
3 .pipe(
4 map(val => {
5 if (val > 2) throw new Error("Invalid Value");
6 return val;
7 }),
8 retry()
9 )
10 .subscribe(val => console.log(val));
11
Retry(0) never retries.
1
2 interval(1000)
3 .pipe(
4 map(val => {
5 if (val > 2) throw new Error("Invalid Value");
6 return val;
7 }),
8 retry(0)
9 )
10 .subscribe(val => console.log(val));
11
ReTryWhen
The RetryWhen Angule RxJs operator retries the failed Observable every time a Notification Observable
emits the next value.
Syntax

1
retryWhen<T>(notifier: (errors: Observable<any>) => Observable<any>):
2
MonoTypeOperatorFunction<T>
3

Where notifier is the callback, which returns the Notification Observable


How it works
We register the notifier callback with the ReTryWhen Operator.
The notifier gets the errors observable as the argument, which emits whenever the source observable
errors
We return the notifier observable, which we build using the errors observable.
The ReTryWhen subscribes to this notifier observable and how it behaves depends on the value emitted
by the notifier observable
 If the notifier emits a value, then ReTryWhen re subscribes the source observable.
 In case of notifier emitting an error, then ReTryWhen also emits an error.
 If the notifier completes, then ReTryWhen does nothing.
ReTryWhen Example
In the following example, map operator throws an error if the val > 2.
The errors are caught by retryWhen. It gets the error observable as its input. We use the pipe operator to
add a tap to print the Retrying message on the console.
This code runs indefinitely as the source will always errors out and there is nothing to stop retryWhen
1
2 import { Component } from "@angular/core";
3 import { map, retryWhen, tap, take } from "rxjs/operators";
4 import { interval, Observable, observable, of, throwError, timer } from "rxjs";
5
6 @Component({
7 selector: "my-app",
8 template: `
9 <h1>Retry And ReTryWhen Example</h1>
10 `,
11 styleUrls: ["./app.component.css"]
12 })
13 export class AppComponent {
14 ngOnInit() {
15 interval(1000)
16 .pipe(
17 map(val => {
18 if (val > 2) throw new Error("Invalid Value");
19 return val;
20 }),
21 retryWhen(
22 error => error.pipe(
23 tap(() => console.log("Retrying... "))))
24 )
25 .subscribe(
26 val => console.log(val),
27 err => console.log(err),
28 () => console.log("Complete")
29 );
30 }
31 }
32
33 **Console **
34
35
36 0
37 1
38 2
39 Retrying..
40 0
41 1
42 2
43 Retrying..
44
Source Code
Returning the error observable as it is also retries the source indefinitely
1
2 interval(1000)
3 .pipe(
4 map(val => {
5 if (val > 2) throw new Error("Invalid Value");
6 return val;
7 }),
8 retryWhen(error => error)
9 )
10 .subscribe(
11 val => console.log(val),
12 err => console.log(err),
13 () => console.log("Complete")
14 );
15
Source Code
Adding a Delay
The following code adds delay of 2000 ms.
1
2 interval(1000)
3 .pipe(
4 map(val => {
5 if (val > 2) throw new Error("Invalid Value");
6 return val;
7 }),
8 retryWhen(
9 error =>
10 error.pipe(
11 tap(() => console.log("error occurred ")),
12 delay(2000),
13 tap(() => console.log("Retrying ..."))
14 )
15 )
16 )
17 .subscribe(
18 val => console.log(val),
19 err => console.log(err),
20 () => console.log("Complete")
21 );
22
Source Code
Notifier observable
As long as the notifier observable emits a value, the retryWhen will re subscribes to the source again.
In the following example, we switch observable to a new observable using SwitchMap operator. The new
observable (of Operator) emits the value 1 after a delay of 1000 ms and the source is resubscribed again.
1
2 interval(1000)
3 .pipe(
4 map(val => {
5 if (val > 2) throw new Error("Invalid Value");
6 return val;
7 }),
8 retryWhen(error =>
9 error.pipe(
10 switchMap(() =>
11 of(1).pipe(
12 delay(1000),
13 tap(() => console.log("of emitted"))
14 )
15 ),
16 tap(() => console.log("Retrying ..."))
17 )
18 )
19 )
20 .subscribe(
21 val => console.log(val),
22 err => console.log(err),
23 () => console.log("Complete")
24 );
25
Source Code
The following uses of() instead of(1). of() does not emit any values but sends a complete notification on
subscription. In this case, RetryWhen does not retry the source but completes. The subscribers will not
receive any notification.
1
2 interval(1000)
3 .pipe(
4 map(val => {
5 if (val > 2) throw new Error("Error: Value greater than 2");
6 return val;
7 }),
8 retryWhen(error =>
9 error.pipe(
10 switchMap(() =>
11 of().pipe(
12 delay(1000),
13 tap(() => console.log("of emitted"))
14 )
15 ),
16 tap(() => console.log("Retrying ..."))
17 )
18 )
19 )
20 .subscribe(
21 val => console.log(val),
22 err => console.error(err),
23 () => console.log("Complete")
24 );
25
Source Code
Here is another interesting example where we switch to interval(3000) observable.
When the error occurs the first time in the source, RetryWhen triggers the interval(3000). When it emits a
value source is re-subscribed.
But, the interval(3000) is going to emit another value after 3000ms. In this case, the RetryWhen will re
subscribes to the source again, even if the source has errored out or already completed.
1
2 interval(1000)
3 .pipe(
4 map(val => {
5 if (val > 2) throw Error;
6 return val;
7 }),
8 retryWhen(error =>
9 error.pipe(
10 tap(() => console.log("error tapped")),
11 switchMap(() =>
12 interval(3000).pipe(tap(() => console.log("interval")))
13 ),
14 tap(() => console.log("Retrying ..."))
15 )
16 )
17 )
18 .subscribe(
19 val => console.log(val),
20 err => console.log(err),
21 () => console.log("Complete")
22 );
23
24 *** Console ***
25 0
26 1
27 2
28 error tapped
29 interval
30 Retrying ...
31 0
32 1
33 interval
34 Retrying ...
35 0
36 1
37 interval
38 Retrying ...
39
40
Source Code
Limiting Retry Attempts
In the example below, we use the scan operator to count the number of tries and throw an error if the
number of attempts exceeds 2.
1
2 interval(1000)
3 .pipe(
4 map(val => {
5 if (val > 2) throw new Error("Invalid Value");
6 return val;
7 }),
8 retryWhen(error =>
9 error.pipe(
10 scan((acc, error) => {
11 if (acc > 2) throw error;
12 console.log("attempt " + acc);
13 return acc + 1;
14 }, 1),
15 delay(3000),
16 tap(() => console.log("Retrying ..."))
17 )
18 )
19 )
20 .subscribe(
21 val => console.log(val),
22 err => console.error(err),
23 () => console.log("Complete")
24 );
25
26
27 *** Console ***
28 0
29 1
30 2
31 attempt 1
32 Retrying ...
33 0
34 1
35 2
36 attempt 2
37 Retrying ...
38 0
39 1
40 2
41 Invalid Value
42
43
Source Code
Use the dealyWhen to increase the time duration between each retries.
1
2 interval(1000)
3 .pipe(
4 map(val => {
5 if (val > 2) throw new Error("Invalid Value");
6 return val;
7 }),
8 retryWhen(error =>
9 error.pipe(
10 scan((acc, error) => {
11 if (acc > 2) throw error;
12 console.log("attempt " + acc);
13 return acc + 1;
14 }, 1),
15 delayWhen(val => timer(val * 2000)),
16 tap(() => console.log("Retrying ..."))
17 )
18 )
19 )
20 .subscribe(
21 val => console.log(val),
22 err => console.error(err),
23 () => console.log("Complete")
24 );
25
Source Code
You can also use the take or takeWhile operator to stop the retries and emit the complete notification.
1
2
interval(1000)
3
.pipe(
4
map(val => {
5
if (val > 2) throw new Error("Invalid Value");
6
return val;
7
}),
8
retryWhen(error =>
9
error.pipe(
10
scan((acc, error) => {
11
console.log("attempt " + acc);
12
return acc + 1;
13
}, 1),
14
take(2),
15
delayWhen(val => timer(val * 2000)),
16
tap(() => console.log("Retrying ..."))
17
)
18
)
19
)
20
.subscribe(
21
val => console.log(val),
22
err => console.error(err),
23
() => console.log("Complete")
24
);
25
}
26
Unsubscribing from an Observable in Angular
1 Comment / March 9, 2023 / 6 minutes of reading
ReTry & ReTryWhen

Angular Tutorial

Subjects in Angular

In this tutorial let us learn how to Unsubscribe from an observable in angular. An observable which is not
Unsubscribed will lead to memory leak & Performance degradation.

Table of Contents
 Why Unsubscribe
 How to Unsubscribe
 When to Unsubscribe
 Various ways to Unsubscribe
o Use Async Pipe
o Using Take or First Operator
o Use Unsubscribe
o Using TakeUntil
 Reference
Why Unsubscribe
In the example below, we have ChildComponent, which subscribes to an observable in
its ngOnInit hook. The observable emits a new value for every 2000 ms.
In the AppComponent, we use the ngIf to show and remove the ChildComponent.
app.component.html
1
2 <h1>Angular Unsubscribe from Observable Example</h1>
3
4 Show Child :
5 <input
6 type="checkbox"
7 id="showChild"
8 name="showChild"
9 import { Component, VERSION } from "@angular/core";
10
11 @Component({
12 selector: "my-app",
13 template: `
14 <h1>Angular Unsubscribe from Observable Example</h1>
15
16 Show Child :
17 <input
18 type="checkbox"
19 id="showChild"
20 name="showChild"
21 [(ngModel)]="showChild"
22 />
23
24 <app-child-component *ngIf="showChild"></app-child-component>
25 `,
26 styleUrls: ["./app.component.css"]
27 })
28 export class AppComponent {
29 name = "Angular " + VERSION.major;
30
31 showChild = false;
32 }
33
34
Child.Component.ts
1
2 import { Component, OnInit } from "@angular/core";
3 import { timer, interval } from "rxjs";
4
5 @Component({
6 selector: "app-child-component",
7 templateUrl: "./child.component.html",
8 styleUrls: ["./child.component.css"]
9 })
10 export class ChildComponent implements OnInit {
11 src = interval(2000);
12 id = Date.now();
13
14 constructor() {}
15
16 ngOnInit() {
17 console.log("Component Created " + this.id);
18
19 this.src.subscribe(value => {
20 console.log("Received " + this.id);
21 });
22 }
23
24 ngOnDestroy() {
25 console.log("Component Destroyed " + this.id);
26 }
27 }
28
29
Source Code
The subscription starts to emit values when the child component is rendered by Angular. But when we
destroy the component, the observable still keeps emitting new values. We can see this in console
window.
If we render the child component again, it starts a new subscription. Now we have two subscriptions
running. As and when we create a new instance of the child component, it will create a new subscription,
and those subscriptions never cleaned up.
How to Unsubscribe
Unsubscribing from an observable as easy as calling Unsubscribe() method on the subscription. It will
clean up all listeners and frees up the memory
To do that, first create a variable to store the subscription
1
2 obs: Subscription;
3
Assign the subscription to the obs variable
1
2 this.obs = this.src.subscribe(value => {
3 console.log("Received " + this.id);
4 });
5
6
Call the unsubscribe() method in the ngOnDestroy method.
1
2 ngOnDestroy() {
3 this.obs.unsubscribe();
4 }
5
6
When we destroy the component, the observable is unsubscribed and cleaned up.
The final code is shown below
Child.Component.ts
1
2 import { Component, OnInit } from "@angular/core";
3 import { timer, interval, Subscription } from "rxjs";
4
5 @Component({
6 selector: "app-child-component",
7 templateUrl: "./child.component.html",
8 styleUrls: ["./child.component.css"]
9 })
10 export class ChildComponent implements OnInit {
11 src = interval(2000);
12 id = Date.now();
13 obs: Subscription;
14
15 constructor() {}
16
17 ngOnInit() {
18 console.log("Component Created " + this.id);
19
20 this.obs = this.src.subscribe(value => {
21 console.log("Received " + this.id);
22 });
23 }
24
25 ngOnDestroy() {
26 console.log("Component Destroyed " + this.id);
27 this.obs.unsubscribe();
28 }
29 }
30
31
Source Code
When to Unsubscribe
There is no need to unsubscribe from every subscription. For Example, the observables, which are finite
in nature. Although it does not harm if you do so.
In Angular you do not have to Unsubscribe in the following scenarios
 The HttpClient Observables like HTTP get & post, etc. They Complete after returning only one
value.
 The Angular Router also emits several observables like paramMap, queryParamMap,
fragment, data, URL, Events, etc. The Router Modules take care of unsubscribing.
 All finite observables.
You need to Unsubscribe in the following scenarios
 Any Observable that you create in your Angular component or Angular services.
 ValueChanges & StatusChanges observables from Angular Forms
 The listens to the DOM events from the Renderer2 service
 All infinite observables.
 When in doubt, always Unsubscribe
Various ways to Unsubscribe
Use Async Pipe
Use Async pipe to subscribe to an observable, it automatically cleans up, when we destroy the
component.
Using Take or First Operator
Convert all infinite observables to finite observable using the Take or First Operators.
The Take Operator emits the first n number of values and then stops the source observable.
1
2 export class AppComponent {
3
4 obs = of(1, 2, 3, 4, 5).pipe(take(2));
5
6 ngOnInit() {
7 this.obs.subscribe(val => console.log(val));
8 }
9 }
10
11 ****Console ******
12 1
13 2
14
The first operator emits the first value and then stops the observable. But It sends an error notification if
does not receive any value.
1
2 export class AppComponent {
3
4 obs = of(1, 2, 3, 4, 5).pipe(first());
5
6 ngOnInit() {
7 this.obs.subscribe(val => console.log(val));
8 }
9 }
10
11 ****Console ******
12 1
13
14
Use Unsubscribe
Using Unsubscribe is the simplest & easiest way.
Store each subscription in a local variable and call unsubscribe on them in the ngOnDestroy hook
1
2 import { Component, OnInit } from "@angular/core";
3 import { timer, interval, Subscription } from "rxjs";
4
5 @Component({
6 selector: "app-child-component",
7 templateUrl: "./child.component.html",
8 styleUrls: ["./child.component.css"]
9 })
10 export class ChildComponent implements OnInit {
11 src1 = interval(1000);
12 src2 = interval(1500);
13 src3 = interval(2000);
14
15 id = Date.now();
16 obs1: Subscription;
17 obs2: Subscription;
18 obs3: Subscription;
19
20 constructor() {}
21
22 ngOnInit() {
23 console.log("Component Created " + this.id);
24
25 this.obs1 = this.src1.subscribe(value => {
26 console.log("Src1 " + this.id);
27 });
28
29 this.obs2 = this.src2.subscribe(value => {
30 console.log("Src2 " + this.id);
31 });
32
33 this.obs3 = this.src3.subscribe(value => {
34 console.log("Src3 " + this.id);
35 });
36 }
37
38 ngOnDestroy() {
39
40 if (this.obs1) this.obs1.unsubscribe();
41 if (this.obs2) this.obs2.unsubscribe();
42 if (this.obs3) this.obs3.unsubscribe();
43
44 console.log("Component Destroyed " + this.id);
45 }
46 }
47
48
Source Code
Using Array to store subscription
Instead of local variable for each subscription, you can create an array and add each subscription into it
1
2 let subs: Subscription[] = [];
3
Push each subscriptions to array
1
2 this.subs.push(
3 this.src1.subscribe(value => {
4 console.log("Src1 " + this.id);
5 })
6 );
7
In the ngOnDestroy hook, call unsubscribe on each subscriptions
1
2 ngOnDestroy() {
3 this.subs.forEach(sub => sub.unsubscribe());
4
5 console.log("Component Destroyed " + this.id);
6 }
7
Source Code
Using TakeUntil
We can make use of TakeUntil Operator.
The takeUntil operator emits values from the source observable until the notifier Observable emits a
value. It then completes the source observable.
To use takeUntil first, we create a notifier observable stop$
1
2 stop$ = new Subject<void>();
3
4
This notifier observable emits a value when the component is destroyed. We do that
in ngOnDestroy hook.
1
2 ngOnDestroy() {
3 this.stop$.next();
4 this.stop$.complete();
5 }
6
7
We add the takeUntil(this.stop$) to all the observable we subscribe. When the component is destroyed
all of them automatically unsubscribed. Remember to add it to the last in the pipe Operator.
1
2 this.src.pipe(takeUntil(this.stop$)).subscribe(value => {
3 console.log("Obs1 " + this.id);
4 });
5
6
Complete code.
1
2 import { Component, OnInit } from "@angular/core";
3 import { timer, interval, Subscription, Subject } from "rxjs";
4 import { takeUntil } from "rxjs/operators";
5
6 @Component({
7 selector: "app-child-component",
8 templateUrl: "./child.component.html",
9 styleUrls: ["./child.component.css"]
10 })
11 export class ChildComponent implements OnInit {
12 stop$ = new Subject<void>();
13 src = interval(2000);
14
15 id = Date.now();
16
17 constructor() {}
18
19 ngOnInit() {
20 console.log("Component Created " + this.id);
21
22 this.src.pipe(takeUntil(this.stop$)).subscribe(value => {
23 console.log("Obs1 " + this.id);
24 });
25
26 this.src.pipe(takeUntil(this.stop$)).subscribe(value => {
27 console.log("Obs2 " + this.id);
28 });
29 }
30
31 ngOnDestroy() {
32 this.stop$.next();
33 this.stop$.complete();
34 console.log("Component Destroyed " + this.id);
35 }
36 }
37
Source Code
Using TakeUntil in a base component
Instead of creating the notifier observable in every component, you can create on in
a BaseComponent and reuse it everywhere.
base.component.ts
1
2 import { Component, OnDestroy } from "@angular/core";
3 import { Subject } from "rxjs";
4
5 @Component({
6 template: ``
7 })
8 export class BaseComponent implements OnDestroy {
9 stop$ = new Subject<void>();
10
11 ngOnDestroy() {
12 this.stop$.next();
13 this.stop$.complete();
14 console.log("BaseComponent Destroyed ");
15 }
16 }
17
18
Extend every component using BaseComponent.
child.component.ts
1
2 import { Component, OnInit } from "@angular/core";
3 import { timer, interval, Subscription, Subject } from "rxjs";
4 import { takeUntil } from "rxjs/operators";
5 import { BaseComponent } from "../base.component";
6
7 @Component({
8 selector: "app-child-component",
9 templateUrl: "./child.component.html",
10 styleUrls: ["./child.component.css"]
11 })
12 export class ChildComponent extends BaseComponent implements OnInit {
13 src = interval(2000);
14
15 id = Date.now();
16
17 constructor() {
18 super();
19 }
20
21 ngOnInit() {
22 console.log("Component Created " + this.id);
23
24 this.src.pipe(takeUntil(this.stop$)).subscribe(value => {
25 console.log("Obs1 " + this.id);
26 });
27
28 this.src.pipe(takeUntil(this.stop$)).subscribe(value => {
29 console.log("Obs2 " + this.id);
30 });
31 }
32
33 ngOnDestroy() {
34 super.ngOnDestroy();
35 console.log("Component Destroyed " + this.id);
36 }
37 }
38
39
Source Code
Note that if you wish you use the constructor or ngOnDestroy in the child component, then remember to
use the super & super.ngOnDestroy() to call the base constructor & ngOnDestroy of the base
component.
Reference
Subjects in Angular
4 Comments / March 9, 2023 / 6 minutes of reading
Unsubscribe from Angular

Angular Tutorial

Replaysubject, behaviorsubject & Asyncsubject

In this tutorial. let us learn RxJs Subject in Angular. The Subjects are special observable which acts as
both observer & observable. They allow us to emit new values to the observable stream using
the next method. All the subscribers, who subscribe to the subject will receive the same instance of the
subject & hence the same values. We will also show the difference between observable & subject. If you
are new to observable then refer to our tutorial on what is observable in angular.

Table of Contents
 What are Subjects ?
 How does Subjects work
 Creating a Subject in Angular
 Subject is an Observable
 Subject is hot Observable
o Cold observable
o Hot observable
 Every Subject is an Observer
 Subjects are Multicast
o Multicast vs Unicast
 Subjects maintain a list of subscribers
 There are other types of subjects
What are Subjects ?
A Subject is a special type of Observable that allows values to be multicasted to many Observers. The
subjects are also observers because they can subscribe to another observable and get value from it,
which it will multicast to all of its subscribers.
Basically, a subject can act as both observable & an observer.
How does Subjects work
Subjects implement both subscribe method and next, error & complete methods. It also maintains a
collection of observers[]

An Observer can subscribe to the Subject and receive value from it. Subject adds them to its collection
observers. Whenever there is a value in the stream it notifies all of its Observers.
The Subject also implements the next, error & complete methods. Hence it can subscribe to another
observable and receive values from it.
Creating a Subject in Angular
The following code shows how to create a subject in Angular.
app.component.ts
1
2 import { Component, VERSION } from "@angular/core";
3 import { Subject } from "rxjs";
4
5 @Component({
6 selector: "my-app",
7 templateUrl: "./app.component.html",
8 styleUrls: ["./app.component.css"]
9 })
10 export class AppComponent {
11
12 subject$ = new Subject();
13
14 ngOnInit() {
15
16 this.subject$.subscribe(val => {
17 console.log(val);
18 });
19
20 this.subject$.next("1");
21 this.subject$.next("2");
22 this.subject$.complete();
23 }
24 }
25
Stackblitz
The code that creates a subject.
1
2 subject$ = new Subject();
3
We subscribe to it just like any other observable.
1
2 this.subject$.subscribe(val => {
3 console.log(val);
4 });
5
The subjects can emit values. You can use the next method to emit the value to its subscribers. Call
the complete & error method to raise complete & error notifications.
1
2 this.subject$.next("1");
3 this.subject$.next("2");
4 this.subject$.complete();
5 //this.subject$.error("error")
6
That’s it.
Subject is an Observable
The subject is observable. It must have the ability to emit a stream of values
The previous example shows, we can use the next method to emit values into the stream.
1
2 this.subject$.next("1");
3 this.subject$.next("2");
4
Subject is hot Observable
Observables are classified into two groups. Cold & Hot
Cold observable
The cold observable does not activate the producer until there is a subscriber. This is usually the case
when the observable itself produces the data.
1
2 import { Component, VERSION } from "@angular/core";
3 import { Subject, of } from "rxjs";
4
5 import { Component, VERSION } from "@angular/core";
6 import { Observable, of } from "rxjs";
7
8 @Component({
9 selector: "my-app",
10 templateUrl: "./app.component.html",
11 styleUrls: ["./app.component.css"]
12 })
13 export class AppComponent {
14 obs1$ = of(1, 2, 3, 4);
15
16 obs$ = new Observable(observer => {
17 console.log("Observable starts");
18 observer.next("1");
19 observer.next("2");
20 observer.next("3");
21 observer.next("4");
22 observer.next("5");
23 });
24
25 ngOnInit() {
26 this.obs$.subscribe(val => {
27 console.log(val);
28 });
29 }
30 }
31
32
Stackblitz
The Producer is one that produces the data. In the above example above it is part of the observable
itself. We cannot use that to emit data ourselves.

Even in the following code, the producer is part of the observable.


1
2 obs1$ = of(1, 2, 3, 4);
3
The producer produces the value only when a subscriber subscribes to it.
Hot observable
The hot observable does not wait for a subscriber to emit the data. It can start emitting the values right
away. The happens when the producer is outside the observable.
Consider the following example. We have created an observable using subject. In the ngOnInit, we emit
the values & close the Subject. That is without any subscribers.
Since there were no subscribers, no one receives the data. But that did not stop our subject from
emitting data.
1
2 import { Component, VERSION } from "@angular/core";
3 import { Subject } from "rxjs";
4
5 @Component({
6 selector: "my-app",
7 templateUrl: "./app.component.html",
8 styleUrls: ["./app.component.css"]
9 })
10 export class AppComponent {
11
12 subject$ = new Subject();
13
14 ngOnInit() {
15 this.subject$.next("1");
16 this.subject$.next("2");
17 this.subject$.complete();
18 }
19 }
20
21
Stackblitz
Now, consider the following example. Here the subjects the values 1 & 2 are lost because the
subscription happens after they emit values.
1
2 import { Component, VERSION } from "@angular/core";
3 import { Subject } from "rxjs";
4
5 @Component({
6 selector: "my-app",
7 templateUrl: "./app.component.html",
8 styleUrls: ["./app.component.css"]
9 })
10 export class AppComponent {
11 subject$ = new Subject();
12
13 ngOnInit() {
14 this.subject$.next("1");
15 this.subject$.next("2");
16
17 this.subject$.subscribe(val => {
18 console.log(val);
19 });
20
21 this.subject$.next("3");
22 this.subject$.complete();
23 }
24 }
25
Stackblitz
Every Subject is an Observer
The observer needs to implement the next, error & Complete callbacks (all optional) to become an
Observer
1
2 import { Component, VERSION } from "@angular/core";
3 import { Observable, Subject } from "rxjs";
4
5 @Component({
6 selector: "my-app",
7 templateUrl: "./app.component.html",
8 styleUrls: ["./app.component.css"]
9 })
10 export class AppComponent {
11 subject$ = new Subject();
12
13 observable = new Observable(observer => {
14 observer.next("first");
15 observer.next("second");
16 observer.error("error");
17 });
18
19 ngOnInit() {
20 this.subject$.subscribe(val => {
21 console.log(val);
22 });
23
24 this.observable.subscribe(this.subject$);
25 }
26 }
27
Stackblitz
The following example creates a Subject & and an Observable
We subscribe to the Subject in the ngOnInit method.
We also subscribe to the observable, passing the subject. Since the subject implements the next method,
it receives the values from the observable and emits them to the subscribers.
The Subject here acts as a proxy between the observable & subscriber.
1
2 this.observable.subscribe(this.subject$);
3
Subjects are Multicast
Another important distinction between observable & subject is that subjects are multicast.
More than one subscriber can subscribe to a subject. They will share the same instance of the
observable. This means that all of them receive the same event when the subject emits it.
Multiple observers of an observable, on the other hand, will receive a separate instance of the
observable.
Multicast vs Unicast
The Subjects are multicast.
Consider the following example, where we have an observable and subject defined. The observable
generates a random number and emits it.
1
2 import { Component, VERSION } from "@angular/core";
3 import { from, Observable, of, Subject } from "rxjs";
4
5 @Component({
6 selector: "my-app",
7 templateUrl: "./app.component.html",
8 styleUrls: ["./app.component.css"]
9 })
10 export class AppComponent {
11 observable$ = new Observable<number>(subscriber => {
12 subscriber.next(Math.floor(Math.random() * 200) + 1);
13 });
14
15 subject$ = new Subject();
16
17 ngOnInit() {
18 this.observable$.subscribe(val => {
19 console.log("Obs1 :" + val);
20 });
21
22 this.observable$.subscribe(val => {
23 console.log("Obs2 :" + val);
24 });
25
26 this.subject$.subscribe(val => {
27 console.log("Sub1 " + val);
28 });
29 this.subject$.subscribe(val => {
30 console.log("Sub2 " + val);
31 });
32
33 this.subject$.next(Math.floor(Math.random() * 200) + 1);
34 }
35 }
36
Stackblitz
We have two subscribers of the observable. Both these subscribers will get different values. This is
because observable on subscription creates a separate instance of the producer. Hence each one will get
a different random number
1
2 this.observable$.subscribe(val => {
3 console.log("Obs1 :" + val);
4 });
5
6 this.observable$.subscribe(val => {
7 console.log("Obs2 :" + val);
8 });
9
Next, we create two subscribers to the subject. The subject emits the value using the random number.
Here both subscribets gets the same value.
1
2 this.subject$.subscribe(val => {
3 console.log("Sub1 " + val);
4 });
5 this.subject$.subscribe(val => {
6 console.log("Sub2 " + val);
7 });
8
9 this.subject$.next(Math.floor(Math.random() * 200) + 1);
10
Subjects maintain a list of subscribers
Whenever a subscriber subscribes to a subject, it will add it to an array of subscribers. This way Subject
keeps track of its subscribers and emits the event to all of them.
There are other types of subjects
What we have explained to you is a simple subject. But there are few other types of subjects. They are
1. ReplaySubject
2. BehaviorSubject
3. AsyncSubject
We will talk about them in the next tutorial.
ReplaySubject, BehaviorSubject & AsyncSubject in Angular
3 Comments / March 9, 2023 / 4 minutes of reading
Subjects in Angular

Angular Tutorial

Angular Subject Example

ReplaySubject, BehaviorSubject & AsyncSubject are special types of subjects in Angular. In this tutorial
let us learn what are they, how they work & how to use them in Angular
Table of Contents
 BehaviorSubject
 ReplaySubject
 AsyncSubject
 Reference
BehaviorSubject
BehaviorSubject requires an initial value and stores the current value and emits it to the new
subscribers.
1
2 import { Component, VERSION } from "@angular/core";
3 import { BehaviorSubject, Subject } from "rxjs";
4
5 @Component({
6 selector: "my-app",
7 templateUrl: "./app.component.html",
8 styleUrls: ["./app.component.css"]
9 })
10 export class AppComponent {
11 subject$ = new BehaviorSubject("0");
12
13 ngOnInit() {
14 this.subject$.subscribe(val => {
15 console.log("Sub1 " + val);
16 });
17
18 this.subject$.next("1");
19 this.subject$.next("2");
20
21 this.subject$.subscribe(val => {
22 console.log("sub2 " + val);
23 });
24
25 this.subject$.next("3");
26 this.subject$.complete();
27 }
28 }
29
30
31
32 ***Result***
33
34 Sub1 0
35 Sub1 1
36 Sub1 2
37 sub2 2
38 Sub1 3
39 sub2 3
40
41
StackBlitz
We create a new BehaviorSubject providing it an initial value or seed value. The BehaviorSubject stores
the initial value.
1
2 subject$ = new BehaviorSubject("0");
3
As soon as the first subscriber subscribes to it, the BehaviorSubject emits the stored value. i.e. 0
1
2 this.subject$.subscribe(val => {
3 console.log("Sub1 " + val);
4 });
5
We emit two more values. The BehaviorSubject stores the last value emitted i.e. 2
1
2 this.subject$.next("1");
3 this.subject$.next("2");
4
Now, Subscriber2 subscribes to it. It immediately receives the last value stored i.e. 2
1
2 this.subject$.subscribe(val => {
3 console.log("sub2 " + val);
4 });
5
ReplaySubject
ReplaySubject replays old values to new subscribers when they first subscribe.
The ReplaySubject will store every value it emits in a buffer. It will emit them to the new subscribers in
the order it received them. You can configure the buffer using the
arguments bufferSize and windowTime
bufferSize: No of items that ReplaySubject will keep in its buffer. It defaults to infinity.
windowTime: The amount of time to keep the value in the buffer. Defaults to infinity.
Example
1
2
3 import { Component, VERSION } from "@angular/core";
4 import { ReplaySubject, Subject } from "rxjs";
5
6 @Component({
7 selector: "my-app",
8 templateUrl: "./app.component.html",
9 styleUrls: ["./app.component.css"]
10 })
11 export class AppComponent {
12 subject$ = new ReplaySubject();
13
14 ngOnInit() {
15 this.subject$.next("1");
16 this.subject$.next("2");
17
18 this.subject$.subscribe(
19 val => console.log("Sub1 " + val),
20 err => console.error("Sub1 " + err),
21 () => console.log("Sub1 Complete")
22 );
23
24 this.subject$.next("3");
25 this.subject$.next("4");
26
27 this.subject$.subscribe(val => {
28 console.log("sub2 " + val);
29 });
30
31 this.subject$.next("5");
32 this.subject$.complete();
33
34 this.subject$.error("err");
35 this.subject$.next("6");
36
37 this.subject$.subscribe(
38 val => {
39 console.log("sub3 " + val);
40 },
41 err => console.error("sub3 " + err),
42 () => console.log("Complete")
43 );
44 }
45 }
46
47 ***Result***
48 Sub1 1
49 Sub1 2
50 Sub1 3
51 Sub1 4
52 sub2 1
53 sub2 2
54 sub2 3
55 sub2 4
56 Sub1 5
57 sub2 5
58 Sub1 Complete
59 sub3 1
60 sub3 2
61 sub3 3
62 sub3 4
63 sub3 5
64 sub3 err
65
Stackblitz
First, we create a ReplaySubject
1
2 subject$ = new ReplaySubject();
3
ReplaySubject emits two values. It will also store these in a buffer.
1
2 this.subject$.next("1");
3 this.subject$.next("2");
4
We subscribe to it. The observer will receive 1 & 2 from the buffer
1
2 this.subject$.subscribe(
3 val => console.log("Sub1 " + val),
4 err => console.error("Sub1 " + err),
5 () => console.log("Sub1 Complete")
6 );
7
We subscribe again after emitting two more values. The new subscriber will also receive all the previous
values.
1
2 this.subject$.next("3");
3 this.subject$.next("4");
4
5 this.subject$.subscribe(val => {
6 console.log("sub2 " + val);
7 });
8
We emit one more value & complete. All the subscribers will receive complete. They will not receive any
further values or notifcations.
1
2 this.subject$.next("5");
3 this.subject$.complete();
4
5
We now fire an error notification and a value. None of the previous subscribers will receive this as they
are already closed.
1
2 this.subject$.error("err");
3 this.subject$.next("6");
4
Now, we subscribe again. The subscriber will receive all the values up to Complete. But will not receive
the Complete notification, instead, it will receive the Error notification.
1
2 this.subject$.subscribe(
3 val => {
4 console.log("sub3 " + val);
5 },
6 err => console.error("sub3 " + err),
7 () => console.log("Complete")
8 );
9
AsyncSubject
AsyncSubject only emits the latest value only when it completes. If it errors out then it will emit an error,
but will not emit any values.
1
2 import { Component, VERSION } from "@angular/core";
3 import { AsyncSubject, Subject } from "rxjs";
4
5 @Component({
6 selector: "my-app",
7 templateUrl: "./app.component.html",
8 styleUrls: ["./app.component.css"]
9 })
10 export class AppComponent {
11 subject$ = new AsyncSubject();
12
13 ngOnInit() {
14 this.subject$.next("1");
15 this.subject$.next("2");
16
17 this.subject$.subscribe(
18 val => console.log("Sub1 " + val),
19 err => console.error("Sub1 " + err),
20 () => console.log("Sub1 Complete")
21 );
22
23 this.subject$.next("3");
24 this.subject$.next("4");
25
26 this.subject$.subscribe(val => {
27 console.log("sub2 " + val);
28 });
29
30 this.subject$.next("5");
31 this.subject$.complete();
32
33 this.subject$.error("err");
34
35
this.subject$.next("6");
36
37
this.subject$.subscribe(
38
val => console.log("Sub3 " + val),
39
err => console.error("sub3 " + err),
40
() => console.log("Sub3 Complete")
41
);
42
}
43
}
44
45
46
**Result **
47
Sub1 5
48
sub2 5
49
Sub1 Complete
50
Sub3 5
51
Sub3 Complete
52
ngular Observable Subject Example Sharing Data Between Components
1 Comment / March 9, 2023 / 4 minutes of reading

In this tutorial, we will show you how to use Subjects in Angular with examples. We learned What
is Subjects in Angular and different types of subjects
like ReplaySubject, BehaviorSubject & AsyncSubject in Angular

Table of Contents
 Angular Subject Example
 Todo Service Using BehaviorSubject
 TodoList Component
 TodoAdd Component
 References
Angular Subject Example
We will build a todo app. Our app has two components.
One is the Todo list component, which displays the list of todos. It also has the option to delete a todo
Another one is Todo add a component, which allows us to add a Todo item.
Both will communicate with each other via Service. Whenever a new todo is added, the service will notify
the Todo list component to update the lists using a observable
Code is available at StackBlitz
Todo Service Using BehaviorSubject
Create the todo.service.ts in the src\app folder.
todo.service.ts
1
2 import { Injectable } from "@angular/core";
3 import { BehaviorSubject } from "rxjs";
4
5 export interface Todo {
6 id: any;
7 value: string;
8 }
9
10 @Injectable()
11 export class TodoService {
12
13 private _todo = new BehaviorSubject<Todo[]>([]);
14 readonly todos$ = this._todo.asObservable();
15
16 private todos: Todo[] = [];
17 private nextId = 0;
18
19 constructor() {}
20
21 loadAll() {
22 this.todos = [];
23 this._todo.next(this.todos);
24 }
25
26 create(item: Todo) {
27 item.id = ++this.nextId;
28 this.todos.push(item);
29 this._todo.next(Object.assign([], this.todos));
30 }
31
32 remove(id: number) {
33 this.todos.forEach((t, i) => {
34 if (t.id === id) {
35 this.todos.splice(i, 1);
36 }
37 this._todo.next(Object.assign([], this.todos));
38 });
39 }
40 }
41
42
Here, we create BehaviorSubject of type Todo[]. Behavior expects us to provide an initial value. We
assign an empty array. The BehaviorSubject will always emit the latest list of Todo items as an array. We
can also use Subject here. But the advantage of BehaviorSubject is that the late subscribers will always
receive the latest list of Todo items immediately on the subscription. We do not have to call
the next method.
1
2 private _todo$ = new BehaviorSubject<Todo[]>([]);
3
4
Also, it is advisable not to expose the BehaviorSubject outside the service. Hence we convert it to
normal Observable and return it. This is because the methods like next, complete or error do not exist
on normal observable. It will ensure that the end-user will not accidentally call them and mess up with it
1
2 readonly todos$ = this._todo.asObservable();
3
The todos will store the todo items in memory. We use the nextId to create the id of the Todo item.
1
2 private todos: Todo[] = [];
3 private nextId = 0;
4
Create pushes the new item to the todos list. Here we use the next method to push the todos list to all
the subscribers. Note that we use the Object.assign to create a new copy of the todos and push it to the
subscribers. This will protect our original copy of the todos list from accidental modification by the user.
1
2 create(item: Todo) {
3 item.id = ++this.nextId;
4
5 //Update database
6 this.todos.push(item);
7 this._todo$.next(Object.assign([], this.todos));
8 }
9
Remove method removes the Todo item based on id and pushes the new list to subscribers.
1
2 remove(id: number) {
3 this.todos.forEach((t, i) => {
4 if (t.id === id) {
5 this.todos.splice(i, 1);
6 }
7 this._todo$.next(Object.assign([], this.todos));
8 });
9 }
10
TodoList Component
TodoListComponent displays the list of Todo items.
todo-list.component.ts
1
2 import { Component, OnInit } from "@angular/core";
3 import { FormBuilder, FormGroup, Validators } from "@angular/forms";
4 import { Observable } from "rxjs";
5 import { map } from "rxjs/operators";
6
7 import { Todo, TodoService } from "./todo.service";
8
9 @Component({
10
11 selector: "app-todo",
12 template: `
13 <div *ngFor="let todo of (todos$ | async)">
14 {{ todo.id }} {{ todo.value }}
15 <button (click)="deleteTodo(todo.id)">x</button>
16 </div>
17 `
18 })
19 export class TodoListComponent implements OnInit {
20 todos$: Observable<Todo[]>;
21
22 constructor(private todoService: TodoService) {}
23
24 ngOnInit() {
25 this.todos$ = this.todoService.todos$;
26 }
27
28 deleteTodo(todoId: number) {
29 this.todoService.remove(todoId);
30 }
31 }
32
We inject todoService
1
2 constructor(private todoService: TodoService) {}
3
And get hold of a reference to the todo$ observable.
1
2 this.todos$ = this.todoService.todos$;
3
We use the async pipes to subscribe to the todos$ observable. No need to worry about unsubscribing
the observable as angular handles it when using async pipes
1
2 <div *ngFor="let todo of (todos$ | async)">
3 {{ todo.id }} {{ todo.value }}
4 <button (click)="deleteTodo(todo.id)">x</button>
5 </div>
6
deleteTodo deletes the Todo item by calling the remove method of the todoService
1
2 deleteTodo(todoId: number) {
3 this.todoService.remove(todoId);
4 }
5
TodoAdd Component
We use TodoAddComponent to add a new Todo item
todo-add.component.ts
1
2 import { Component, OnInit } from "@angular/core";
3 import { FormBuilder, FormGroup, Validators } from "@angular/forms";
4 import { Observable } from "rxjs";
5 import { map } from "rxjs/operators";
6
7 import { Todo, TodoService } from "./todo.service";
8
9 @Component({
10 selector: "app-todo-add",
11 template: `
12 <div>
13 <form [formGroup]="todoForm" (submit)="onSubmit()">
14 <p>
15 <input type="text" id="value" name="value" formControlName="value" />
16 </p>
17
18 <button type="submit">Add Item</button><br />
19 </form>
20 </div>
21 `
22 })
23 export class TodoAddComponent implements OnInit {
24 todos$: Observable<Todo[]>;
25 todoForm: FormGroup;
26
27 constructor(
28 private todoService: TodoService,
29 private formBuilder: FormBuilder
30 ){
31 this.todoForm = this.formBuilder.group({
32 id: [""],
33 value: ["", Validators.required]
34 });
35 }
36
37 ngOnInit() {
38 this.todos$ = this.todoService.todos$;
39 }
40
41 onSubmit() {
42 this.todoService.create(this.todoForm.value);
43 this.todoForm.get("value").setValue("");
44 }
45 }
46
47
First inject todoService
1
2 constructor(
3 private todoService: TodoService,
4 private formBuilder: FormBuilder
5 )
6
We get hold of the todos$ observable. We are not doing anything with it But you can subscribe to it to
get the latest list of Todo items.
1
2 ngOnInit() {
3 this.todos$ = this.todoService.todos$;
4 }
5
onSubmit method creates a new Todo item by calling the create method of the todoService.
1
2 onSubmit() {
3 this.todoService.create(this.todoForm.value);
4 this.todoForm.get("value").setValue("");
5 }
6
app.component.html
1
2 <app-todo-add></app-todo-add>
3 <app-todo></app-todo>
4

You might also like