0% found this document useful (0 votes)
312 views158 pages

Angular Observable Tutoria1

The document provides an Angular Observable tutorial covering key concepts like Reactive programming, Observables, Observers, and RxJS. It explains that Observables allow working with asynchronous data streams and are heavily used in Angular. The tutorial defines Observables and Observers, shows how to create Observables from different data sources, subscribe to Observables, and handle events like values, errors and completion. It also lists some common Observable operators and provides a sample code example to demonstrate basic usage of Observables in Angular.

Uploaded by

vrjs27 v
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
312 views158 pages

Angular Observable Tutoria1

The document provides an Angular Observable tutorial covering key concepts like Reactive programming, Observables, Observers, and RxJS. It explains that Observables allow working with asynchronous data streams and are heavily used in Angular. The tutorial defines Observables and Observers, shows how to create Observables from different data sources, subscribe to Observables, and handle events like values, errors and completion. It also lists some common Observable operators and provides a sample code example to demonstrate basic usage of Observables in Angular.

Uploaded by

vrjs27 v
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 158

Angular Observable Tutorial

14 Comments / August 2, 2023 / 11 minutes of reading


Angular Decorators

Angular Tutorial

Create Observable from a string, array. object, collection

The Angular Observable tutorial covers what is observable and how to use
Observables in Angular applications. When we talk about Angular Observable,
we hear a lot of terms like Reactive programming, data streams, Observable,
Observers, RxJS, etc. It is essential to understand these terms before we start
using the observables.

Rx stands from Reactive programming. It is defined as programming with


asynchronous data streams. So it is important that you understand what is
data stream is.
Table of Contents
 What is a data stream
 Reactive Programming
 What is RxJS
 Observable in Angular
 What is an Observable in Angular
 Who are observers (subscribers)
 Angular Observable tutorial
o Import the required libraries
o Observable Creation
o Subscribing to the observable
o Adding interval
o Error event
o Complete Event
 Observable Operators
 Unsubscribing from an Observable
 References
 Summary

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 Observable
14 Tutorial</a>
15 `
16 })
17 export class AppComponent implements OnInit {
18
19
20 obs = new Observable(observer => {
21 console.log('Observable starts');
22 observer.next('1');
23 observer.next('2');
24 observer.next('3');
25 observer.next('4');
26 observer.next('5');
27 });
28
29 ngOnInit() {
30 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);
8 setTimeout(() => { observer.error("error emitted") }, 3500); //sending error 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
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.

To learn more about it refer to the tutorial Unsubscribing from an Observable in


Angular.

References
1. observables
2. RX-library
3. observables in angular
4. Practical observable usage
5. Comparing observables
6. Observable Design Pattern

Summary
Reactive programming is about programming the stream. The RxJS library
brings Reactive Programming into Angular. Using RxJs, we can create an
observable, which can emit the next value, error, and complete signals to the
subscriber of the observable.

Create observable from a string, array &


object in angular
8 Comments / March 9, 2023 / 5 minutes of reading
Angular Observable Tutorial

Angular Tutorial

Observable from Event

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
BEST ANGULAR BOOKS
The Top 8 Best Angular Books, which helps you to get started with Angular
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 '@angular/core';
3 import { Observable, of, from, fromEvent } from 'rxjs';
4 import { debounceTime } from 'rxjs/operators';
5
6 @Component({
7 selector: 'app-root',
8 templateUrl: './app.component.html',
9 styleUrls: ['./app.component.css']
10 })
11 export class AppComponent implements AfterViewInit , OnInit, OnDestroy {
12
13 title = 'Angular fromEvent Example';
14
15 @ViewChild('btn', { static: true }) button: ElementRef;
16
17 buttonSubscription
18
19 constructor(private elm: ElementRef) {
20 }
21
22 ngOnInit() {
23 }
24
25
26 ngAfterViewInit() {
27 this.buttonClick();
28 }
29
30
31 buttonClick() {
32 this.buttonSubscription = fromEvent(this.button.nativeElement, 'click')
33 .pipe(debounceTime(300))
34 .subscribe(res => console.log(res));
35 }
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

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

References
1. RxJs Library
2. Operators
3. Pipe API
4. Map API
5. Tap API
6. Filter API
Read More
1. Angular Observable Tutorial
2. Create Observable using array, number & string etc
3. Create Observable from event using fromEvent

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.

00:00/00:00

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

References
1. Map API
Read More
1. Angular Observable

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.

00:00/00:00

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

References
1. Map API
Read More
1. Angular Observable

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

Reference
 Tap
 Debug RxJs
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.
00:15/03:20

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

References
1. ExhaustMap API
Read More
1. Angular HTTP Get
2. SwitchMap in Angular
3. MergeMap in Angular
4. ConcatMap in Angular
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
Source Code

References
 take
 takeUntil
 takeWhile
 takeLast
Angular ExhaustMap

Angular Tutorial

First, Last & Single

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**
6 4
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?:
2
D) :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**
6 2
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
2 single<T>(predicate?: (value: T, index: number, source: Observable<T>) => boolean): 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
6 3
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**
5 1
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

References
1. first
2. last
3. single
Take, TakeUntil, TakeWhile, TakeLast

Angular Tutorial

Skip, SkipUntil, SkipWhile & SkipLast

Skip, SkipUntil, SkipWhile & SkipLast


Operators in Angular
2 Comments / March 9, 2023 / 4 minutes of reading
First, Last & Single

Angular Tutorial

Scan & Reduce

The skip operators in Angular skips the values from the source observable based
on a condition. The Skip, SkipUntil, SkipWhile skips the values from the start of
the source. The SkipLast Operator skips elements from the end of the source.
Table of Contents
 Skip
o Skip Example
 SkipWhile
o SkipWhile Example
o Filter Vs SkipWhile
 SkipUntil
o SkipUntil Example
 SkipLast
o SkipLast Example
o SkipLast delays the values
 Reference

Skip
The skip operator skips the first count number of values from the source
observable and returns the rest of the source as an observable
Syntax
1
2 skip<T>(count: number): MonoTypeOperatorFunction<T>
3

Skip Example
The example below skip(5) ignores the first 5 values & returns the rest of the
observable as it is.
1
2 import { Component } from "@angular/core";
3 import { skip } from "rxjs/operators";
4 import { interval, of } from "rxjs";
5
6 @Component({
7 selector: "my-app",
8 template: `
9 <h1>Skip Example</h1>
10
11 <br />
12 <br />
13 `,
14 styleUrls: ["./app.component.css"]
15 })
16 export class AppComponent {
17 ngOnInit() {
18 of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
19 .pipe(
20 skip(5),
21 )
22 .subscribe(val => console.log(val));
23 }
24 }
25
26
27 ** Console **
28 6
29 7
30 8
31 9
32 10
33
Source Code

SkipWhile
The SkipWhile operator skips values from the source observable as long as the
specified condition is true. But once the condition becomes false, it starts to
emit the values and continues to do so even if the condition becomes true
again.

Syntax
1
2 skipWhile<T>(predicate: (value: T, index: number) => boolean): MonoTypeOperatorFunction<T>
3

SkipWhile Example
1
2 of( 2, 4, 5, 6, 7, 8, 9, 10)
3 .pipe(
4 skipWhile(val => val % 2==0),
5 )
6 .subscribe(val => console.log(val));
7
8
9 **Console**
10 5
11 6
12 7
13 8
14 9
15 10
16

Filter Vs SkipWhile
The Filter operator and SkipWhile operator uses a predicate to filter out the
values.
The SkipWhile skips the values if the predicate is true, While the filter emits the
values if the predicate is true.
Once the predicate becomes false, the SkipWhile stops using the predicate and
emits all the remaining values. The filter keeps using the predicate to filter out
the remaining values.
Filter Example
1
2 import { Component } from "@angular/core";
3 import { filter } from "rxjs/operators";
4 import { interval, of, timer } from "rxjs";
5
6 @Component({
7 selector: "my-app",
8 template: `
9 <h1>Filter Example</h1>
10 `,
11 styleUrls: ["./app.component.css"]
12 })
13 export class AppComponent {
14 ngOnInit() {
15 of(2, 4, 5, 6, 7, 8, 9, 10)
16 .pipe(
17 filter(val => {
18 return val %2==0;
19 }),
20 )
21 .subscribe(val => console.log(val));
22 }
23 }
24
25
26 ***Console***
27 2
28 4
29 6
30 8
31 10
32

SkipUntil
The SkipUntil operator skips the values from the source observable as long as
the second observable does not emit any value. But once the second observable
emits a value, it starts to emit the values and continues to do so as long as the
source emits values.
It is very similar to SkipWhile except that the condition is provided by another
observable.

Syntax

1
2 skipUntil<T>(notifier: Observable<any>): MonoTypeOperatorFunction<T>
3

SkipUntil Example
The interval creates an observable, which emits a value for every 1000 ms. The
SkipUntil operator uses the timer(6000) observable, which emits a value after
6000ms. Hence the SkipUntil skips the first 5 values (0 to 4) and starts to emit
the values from 5
1
2 interval(1000)
3 .pipe(
4 skipUntil(timer(6000)),
5 )
6 .subscribe(val => console.log(val));
7
8 ***Console **
9 5
10 6
11 7
12 8
13 ....
14
Source Code

SkipLast
The SkipLast operator skips the last count number of values from the source
observable and returns the rest of the source as an observable.
It is exactly opposite of skip(count), which skips the first count number of values
Syntax
1
2 skipLast<T>(count: number): MonoTypeOperatorFunction<T>
3

SkipLast Example
In the following example, the skiplast(5) will skip the last 5 values (i.e 6 to 10)

1
2 of(1,2,3,4,5,6,7,8,9,10)
3 .pipe(
4 skipLast(5)
5 )
6 .subscribe(val => console.log(val));
7
8 **Console*
9 1
10 2
11 3
12 4
13 5
14
Source Code

SkipLast delays the values


SkipLast(count) waits until it receives the count number of values from the
source, before it starts emitting the values.
In the above example, the skipLast does not emit any values till the values 5.
When it receives the value 6, it emits the value 1. You can see it by using the tap
operator.
1
2 of(1,2,3,4,5,6,7,8,9,10)
3 .pipe(
4 tap(val => {
5 console.log("tap " + val);
6 }),
7 skipLast(5)
8 )
9 .subscribe(val => console.log(val));
10
11
12 **Console**
13 tap 1
14 tap 2
15 tap 3
16 tap 4
17 tap 5
18 tap 6
19 1
20 tap 7
21 2
22 tap 8
23 3
24 tap 9
25 4
26 tap 10
27 5
28

Reference
 skip
 skipUntil
 skipWhile
 skipLast
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.
Table of Contents
 Scan in Angular
o Scan Example
 Reduce in Angular
o Reduce Example
 References

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
Source Code

References
Reduce

 Scan
Read More
Skip, SkipUntil, SkipWhile & SkipLast

Angular Tutorial

Debounce & DebounceTime

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
2 debounceTime<T>(dueTime: number, scheduler: SchedulerLike = async): 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
Source Code

Reference
debounce

 debounceTime
Read More
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
 Delay
 delayWhen
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
Source Code

References
ThrowError API
Read More
Delay & DelayWhen

Angular Tutorial

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
Source Code

References
1. catchError
2. throwError
3. retry API
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
2 retryWhen<T>(notifier: (errors: Observable<any>) => Observable<any>): 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

References
ReTry

 ReTryWhen
Read More
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.

Re

You might also like