puddlejumper26 / blogs

Personal Tech Blogs
4 stars 1 forks source link

Angular RxJS tap #127

Open puddlejumper26 opened 4 years ago

puddlejumper26 commented 4 years ago

Recently cause staying at home, so I re-read the Angular official doc. And found out there are some new codes inside the guides, or may be I didn't read carefully enough? Seems not possible, I have read these files at least once per day for the last half year. Or may be it happened in a parallel world? Anyway, the new codes are

getHeroes( ): Observable<Hero[ ]> {
  return this.http.get<Hero[ ]>( this.heroesUrl )
    .pipe(
      tap( _ => this.log( 'fetched heroes' )),
      catchError( this.handleError<Hero[]>( 'getHeroes', [ ] ))
    );
}

RxJS tap performs side effects for every value emitted by source Observable and returns an Observable identical to the source Observable until there is no error. tap is the pipeable operator and it is the changed name of the RxJS do operator.

Angular 6 uses RxJS 6 that has been shipped with pipeable operators which can be used independent of an Observable. To avoid the conflict with JavaScript keyword, some RxJS operators name has been changed such as

do changed to tap, catch changed to catchError, switch changed to switchAll finally changed to finalize.

These operators are imported from rxjs/operators. For example tap is imported as following.

import { tap } from 'rxjs/operators'; 

tap

tap is a RxJS pipeable operator that returns identical Observable as source Observable and can be used to perform side effect such as logging each values emitted by source Observable.

Pipeable operators such as tap, are used within **pipe** function of Observable.

tap performs side effects only when the Observable returned by tap is subscribed.

tap can be used to debug values emitted by Observable or to perform any side effect.

public tap(nextOrObserver: Observer | function, error: function, complete: function): Observable

tap has three optional parameters. **nextOrObserver**: A normal Observable object to perform side effect. **error**: Callback for errors in source Observable. **complete**: Callback for completion of the source.

Example

of( 1, 2, 3, 4 ).pipe(
 tap ( el => console.log("Process "+ el ),
    err => console.error( err ),
    ( ) => console.log( "Complete" )
 ),
 filter( n => n % 2 === 0 )
).subscribe( el => console.log( "Even number: "+ el )); 

Result

Process 1
Process 2
Even number: 2
Process 3
Process 4
Even number: 4
Complete 

In the above example we can see that first callback of tap is logging each value emitted from source Observable. Second callback is to log error but there is no error in source Observable hence error is not logged. Third callback is logging the message of completion that all values have been emitted from source Observable.

As the **parameters** of the tap is **optional**, we can also use tap as following.

of(1, 2, 3, 4).pipe(
  tap(el => console.log("Process "+ el)),
  filter(n => n % 2 === 0)
).subscribe(el => console.log("Even number: "+ el)); 

We can also use tap multiple times to debug values at different stages.

of(1, 2, 3, 4).pipe(
  tap(el => console.log(el)),
  filter(n => n % 2 === 0),
  tap(el => console.log(el)),
  map(n => n + 10),
  tap(el => console.log(el)),
  scan((sum, n) => sum + n),
  tap(el => console.log(el))
).subscribe(result => console.log("Result: "+ result)); 

Reference