Angular + RxJS map
November 12, 2018
This page will walk through Angular and RxJS map
operator example. RxJS map
applies a given function to each element emitted by the source Observable
and emits the resulting values as an Observable
. RxJS map
is imported from rxjs/operators
. The map
is a pipeable operator. In RxJS 6, Observable
uses pipeable operators using its pipe
instance method. RxJS map
can be used with other pipeable operators. RxJS map
is different from JavaScript array map
. Here on this page we will provide RxJS map
operator example. We will also provide error handling using retry
and catchError
operators with map
. Now find the complete example step by step.
Contents
Technologies Used
Find the technologies being used in our example.1. Angular 7.0.0
2. Angular CLI 7.0.3
3. TypeScript 3.1.1
4. Node.js 10.3.0
5. NPM 6.1.0
6. RxJS 6.3.3
Observable and map
map
is a RxJS pipeable operator. map
applies a given function to each element emitted by the source Observable
and emits the resulting values as an Observable
. map
is imported as following.
import { map } from 'rxjs/operators';
map
is used with pipe
which is an instance method of Observable
.
Suppose we have an
Observable
of a string that contains comma separated names.
getStdNames(): Observable<string> { return of("Mahesh, Krishna, Ram"); }
Observable
of array of names.
stdNames$: Observable<string[]>; getStdNames() { this.stdNames$ = this.bookService.getStdNames().pipe( map(res => res.split(",")) ); }
stdNames$
as following.
<ul> <li *ngFor="let name of stdNames$ | async" > {{name}} </li> </ul>
Observable
instance.
this.bookService.getStdNames().pipe( map(res => res.split(",")) ) .subscribe(names=> names.forEach(name => console.log(name)));
Using map with Other RxJS Operators
Here we will usemap
with filter
and scan
. Suppose we have following data.
getNumbers(): Observable<number> { return of(1, 2, 3, 4, 5, 6, 7); // Synchronously data will be emitted. }
map
with filter
and scan
operators.
calcData() { this.bookService.getNumbers().pipe( filter(n => n % 2 === 1), map(n => n + 10), scan((sum, n) => sum + n) ) .subscribe(result => console.log(result)); }
getNumbers()
will be first processed by filter
operator, then map()
and then scan
.
Error Handling: map with retry and catchError
We handle error usingretry
and catchError
operators. In case of failure, retry
operator retries to fetch record for the given number of times. catchError
operator caches the error thrown by any operator, if there is any error. Find the code snippet to use map
operator with error handling.
getCountryStates() { this.mapDemoService.getCountry().pipe( retry(2), map(country => country.getCountryStates()), catchError(err => { console.error(err); return of([]); }) ) .subscribe(res => this.countryStates = res); }
JavaScript Array map vs RxJS map
Suppose we have following array.let cities = ["Varanasi", "Mathura", "Ayodhya"];
map
applies a given function to each element of the array and returns the modified array.
cities.map(c => "Holy "+ c) .forEach(el => console.log(el));
map
will iterate the array and apply given function to each element and finally returns array with modified data. Find the output.
Holy Varanasi Holy Mathura Holy Ayodhya
map
operator applies a given function to each element emitted by source Observable
and returns Observable
instance with modified data.
of(cities).pipe( map(dataArray => dataArray.join(", ")) ).subscribe(res => console.log(res));
map
will receive an array emitted by source Observable
but this RxJS map
will not iterate the array. The given function will be applied on the array. Here we are applying join
function on the array and finally RxJS map
will return the Observable
instance with modified data. Find the output.
Varanasi, Mathura, Ayodhya
Complete Example
map-demo.component.tsimport { Component, OnInit } from '@angular/core'; import { Observable, of } from 'rxjs'; import { map, filter, scan, retry, catchError } from 'rxjs/operators'; import { MapDemoService } from './map-demo.service'; @Component({ selector: 'app-map-demo', templateUrl: './map-demo.component.html' }) export class MapDemoComponent implements OnInit { stdNames$: Observable<string[]>; countryName$: Observable<string>; countryStates: string[]; constructor(private mapDemoService: MapDemoService) { } ngOnInit() { this.getStdNames(); this.calcData(); this.getCountryName(); this.getCountryStates(); let cities = ["Varanasi", "Mathura", "Ayodhya"]; //Using JavaScript Array map cities.map(c => "Holy "+ c) .forEach(el => console.log(el)); //Using RxJS map of(cities).pipe( map(dataArray => dataArray.join(", ")) ).subscribe(res => console.log(res)); } //Using map getStdNames() { this.stdNames$ = this.mapDemoService.getStdNames().pipe( map(res => res.split(",")) ); this.mapDemoService.getStdNames().pipe( map(res => res.split(",")) ) .subscribe(names=> names.forEach(name => console.log(name))); } //Using filter, map and scan calcData() { this.mapDemoService.getNumbers().pipe( filter(n => n % 2 === 1), map(n => n + 10), scan((sum, n) => sum + n) ) .subscribe(result => console.log(result)); } //Using map and catchError getCountryName() { this.countryName$ = this.mapDemoService.getCountry().pipe( map(country => country.getCountryName()), catchError(err => { console.error(err); return of(""); }) ); } //Using retry, map and catchError getCountryStates() { this.mapDemoService.getCountry().pipe( retry(2), map(country => country.getCountryStates()), catchError(err => { console.error(err); return of([]); }) ) .subscribe(res => this.countryStates = res); } }
<b>Student Names</b> <ul> <li *ngFor="let name of stdNames$ | async" > {{name}} </li> </ul> <b>Country Name</b> <div *ngIf="countryName$ | async as myCountryName"> {{myCountryName}} </div> <b>Country States</b> <ul> <li *ngFor="let state of countryStates" > {{state}} </li> </ul>
import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; import { MyCountry } from './my-country'; @Injectable({ providedIn: 'root' }) export class MapDemoService { getNumbers(): Observable<number> { return of(1, 2, 3, 4, 5, 6, 7); } getStdNames(): Observable<string> { return of("Mahesh, Krishna, Ram"); } getCountry(): Observable<MyCountry> { return of(new MyCountry()); } }
export class MyCountry { getCountryName() { return "India"; } getCountryStates() { return ["UP", "MP", "Assam", "Kerla"]; } }
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-map-demo></app-map-demo> ` }) export class AppComponent { }
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { HttpClientModule } from '@angular/common/http'; import { AppComponent } from './app.component'; import { MapDemoComponent } from './map-demo.component'; import { MapDemoService } from './map-demo.service'; @NgModule({ imports: [ BrowserModule, HttpClientModule, FormsModule, ], declarations: [ AppComponent, MapDemoComponent ], providers: [ ], bootstrap: [ AppComponent ] }) export class AppModule { }
Run Application
To run the application, find the steps.1. Download source code using download link given below on this page.
2. Use downloaded src in your Angular CLI application. To install Angular CLI, find the link.
3. Run ng serve using command prompt.
4. Access the URL http://localhost:4200
Find the print screen of the output.

References
RxJS ObservableAngular: The RxJS library
Pipeable Operators