SwitchMap In Angular

SwitchMap In Angular

In this article, we will learn about the SwitchMap in Angular for example. The Angular SwitchMap converts each value from the source observable into an inner observable, subscribes to it, and then begins emitting its data. For each value it receives from the Source, it creates a new inner observable. It unsubscribes from all previously produced inner observables whenever it generates a new inner observable. Essentially, it shifts to the most recent observable and ignores all others.

Syntax

The SwitchMap operator has the following syntax.

switchMap(project: (value: T, index: number) => O): OperatorFunction<t observedvalueof="">)

project: We use this function to alter the values emitted by the source observable. There are two arguments that the project can accept. The first is value, which refers to the value emitted by the source observable. The index number is the second argument. The index number starts at 0 for the first value emitted and increases by one for each item emitted after that. It's comparable to an array's index. An observable must be returned by the project function.

SwitchMap Example

In order to use SwitchMap in Angular, we must first import it into our Component or Service.

import { switchMap } from 'rxjs/operators';

In Angular, the following code demonstrates how to use SwitchMap. We have two observables: srcObservable emitting 1,2,3,4 and innerObservable emitting 'A','B','C','D'.

let srcObservable= of(1,2,3,4)
let innerObservable= of('A','B','C','D')
 
srcObservable.pipe(
  switchMap( val => {
    console.log('Source value '+val)
    console.log('starting new observable')
    return innerObservable
  })
)
.subscribe(ret=> {
  console.log('Recd ' + ret);
})
 
 
//Output
Source value 1
starting new observable
Recd A
Recd B
Recd C
Recd D
Source value 2
starting new observable
Recd A
Recd B
Recd C
Recd D
Source value 3
starting new observable
Recd A
Recd B
Recd C
Recd D
Source value 4
starting new observable
Recd A
Recd B
Recd C
Recd D

The switchMap's first argument is the project function. The values are retrieved from the srcObservable. It produces a new observable, innerObservable, for each value it receives from the srcObservable (i.e. 1,2,3, and 4).

The innerObservable returned by the project function is automatically subscribed to by SwitchMap. The values (A, B,C, D) are pushed to the stream by the innerObservable.

As a result, the values A, B, C, and D will be delivered four times to subscribers. For each value of the srcObservable, do this once.

SwitchMap Vs Map

Value is emitted as an observable by the map operators. The SwitchMap constructs an inner observable subscribes to it and emits the value of that observable as an observable.

The distinction between them is seen in the following example.

By multiplying the value from the source observable by two, the map operator below transfers it to a new value. The data is subsequently written to the observable stream. The values 2,4,6, and 8 will be sent to subscribers.

let obs= of(1,2,3,4)
 
//Using MAP
obs.pipe(
  map(val => {
    return val*2      //Returning Value
  })
)
.subscribe(ret=> {
  console.log('Recd from map : ' + ret);
})
 
//Output
Recd from map : 2
Recd from map : 4
Recd from map : 6
Recd from map : 8

The following code can be written using SwitchMap to implement the above code. The only difference is in how the project function returns the new value. The map example returns the value as val*2, whereas the SwitchMap uses the of function to return a new observable (of(val*2)). It also subscribes to and emits the value of the newly formed observable to the stream.

let obs= of(1,2,3,4)
 
obs.pipe(
   switchMap( val => {
     return of(val*2)  //Returning observable
   })
)
.subscribe(ret=> {
  console.log('Recd from switchMap : ' + ret);
 })
 
//Output
Recd from switchMap : 2
Recd from switchMap : 4
Recd from switchMap : 6
Recd from switchMap : 8

SwitchMap switches to the most recent observable

SwitchMap unsubscribes from the previous inner observable whenever it subscribes to a new one.

Using the fromEvent method, we build an observable from a button's click event in the following example. The interval method is used by the SwitchMap operator to return an observable. The interval method generates an endless observable that emits a series of integers separated by a time interval.

import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
import { of, from, fromEvent, interval, Observable } from 'rxjs';
import { switchMap, map, catchError } from 'rxjs/operators';
 
@Component({
  selector: 'app-root',
  template: `<button button="">Click Me</button>`,
})
export class AppComponent implements AfterViewInit{
 
  @ViewChild('button',{static:true}) button;
  clicks$:Observable<any>;
 
  ngAfterViewInit() {
    this.clicks$ = fromEvent(this.button.nativeElement, 'click');
    this.switchExample();
  }
 
  switchExample() {
    this.clicks$
      .pipe(
        switchMap(() => {
          return interval(500)
        })
      )
      .subscribe( val => console.log(val));
  }
}

The clicks observable emits its first value when you click the button. The interval observable is replaced with the switchMap, which emits values starting at 0 every 500ms.

When you click again, the switchMap unsubscribes from the previous interval observable and subscribes to a new one, which emits values starting at 0.

SwitchMap Example In Angular



Using SwitchMap in Angular

The SwitchMap in Angular has a variety of real-world applications.

With Route Parameters

We must read it in our component class when we use the Angular Router to pass a parameter to a route. We obtain the id by subscribing to the paramMap. The product data is then retrieved using the id.

The code is as follows:

ngOnInit() {
    this._Activatedroute.paramMap.subscribe(params => { 
       this.service.getProduct(+params.get('id')) 
          .subscribe((product: Product) => this.product = product);
    });
  }

Consider the following scenario: the user goes to the /product/1 route. The query will be sent to the database by the service to acquire the Product with id 1 from the database. The user now chooses to go to the /product/2 route. Another query for the Product will be sent to the database as a result of this. It's possible that the second query's response will arrive before the first query. In this case, we'll be on the /product/2 route, with our component displaying data from product 1.

Using the switchMap, we can simply address the problem described above. SwitchMap unsubscribes from all prior observables when it produces the second observable. As a result, even if Product 1 data is late, it will be rejected.

ngOnInit() {
 
    this.activatedRoute.paramMap
      .pipe(
        switchMap((params: Params) => {
          return this.service.getProduct(params.get('id'))
        }
        ))
      .subscribe((product: Product) => this.product = product);
}

Angular Forms ValueChanges event

When we subscribe to the ValueChanges event and use it to obtain data from the back end, we can fall into similar scenarios as discussed previously.

this.mainForm.get("productCode").valueChanges
.pipe(
  debounceTime(700)
)
.subscribe(val=> {
  this.queryDepositData(val)
    .subscribe(data => {
      this.product=data;
  })
})

The switchMap ensures that only the last observable's result is used to populate the Product.

this.mainForm.get("productCode").valueChanges
.pipe(
  debounceTime(700),
  switchMap(val => {
    return this.queryDepositData();
  })
)
.subscribe(data => {
  this.product=data;
})

The debounceTime operator is also used in this example, which emits a value from the source Observable only after a certain amount of time has passed without another source emission.

Conclusion

In this article, we learned what is SwitchMap and how to use it in Angular for example. 

I hope this article helps you and you will like it.👍

If you have any doubt or confusion then free to ask in the comment section.

Post a Comment

Previous Post Next Post