Angular Observable Tutoria1
Angular Observable Tutoria1
Angular Tutorial
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.
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 with emit error and complete events
As said earlier the stream of data can be anything. For Example
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.
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
1. Observable
2. Observers ( Subscribers)
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()
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
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.
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
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
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.
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.
Angular Tutorial
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
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
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
From Operator
From Operator takes only one argument that can be iterated and converts it
into an observable.
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
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
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
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.
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
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
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
Angular Tutorial
Filter
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.
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.
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
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
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.
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.
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
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
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
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
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'.
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 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
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 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
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.
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
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
Angular Tutorial
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'.
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
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
Angular Tutorial
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
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
Angular Tutorial
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
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
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
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
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
Angular Tutorial
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
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
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
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
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 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.
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
References
ThrowError API
Read More
Delay & DelayWhen
Angular Tutorial
Angular Tutorial
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
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.
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
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.
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
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
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.
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.
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.
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.
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