The Angular Tap RxJs operator returns an observable identical to the source. It does not modify the stream in any way. The tap operator is useful for logging the value, debugging the stream for the correct values, or performing any other side effects.
Syntax
1 2 3 | tap(nextOrObserver: function, error: function, complete: function): Observable |
Tap Operator Example
In the following example, we create an observable using the of operator. We use the pipe to chain the tap operator, which logs the values of the source observable into the console.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | import { Component, VERSION } from '@angular/core'; import { tap } from 'rxjs/operators'; import { of } from 'rxjs'; @Component({ selector: 'my-app', template: ` <h1>Tap Example</h1> <br /> <br /> Read <a href="https://www.tektutorialshub.com/angular/tap-operator-in-angular-observable/">Tap in Angular</a> `, }) export class AppComponent { ngOnInit() { of(1, 2, 3, 4, 5) .pipe( tap((val) => { console.log('Tap ' + val); }) ) .subscribe({ next: (val) => console.log('at Subscriber ' + val) }); // older syntax //.subscribe(val => console.log("at Subscriber " + val)); } } ***Console Tap 1 at Subscriber 1 Tap 2 at Subscriber 2 Tap 3 at Subscriber 3 Tap 4 at Subscriber 4 Tap 5 at Subscriber 5 |
The results will be the same if we pass the console.log
function to the tap operator.
1 2 3 4 5 | of(1, 2, 3, 4, 5) .pipe(tap(console.log)) .subscribe(val => console.log("at Subscriber " + val)); |
Tap does not modify the source observable in any way
For Example, changing the source any way in the tap operator, as in the example below, will have no effect.
1 2 3 4 5 6 7 8 9 10 11 | of(1, 2, 3, 4, 5) .pipe( tap(val => { val=val+1 console.log("Tap " + val); return val; }) ) .subscribe(val => console.log("at Subscriber " + val)); |
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 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | of(1, 2, 3, 4, 5) .pipe( tap(val => { console.log("before " +val); }), map(val => { return val + 5; }), tap(val => { console.log("after " +val); }) ) .subscribe(val => console.log(val)); **Console** before 1 after 6 6 before 2 after 7 7 before 3 after 8 8 |
Error and complete callbacks
We can also use the tap operator to log the error and complete callbacks as shown in the example below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | import { Component, VERSION } from "@angular/core"; import { FormControl, FormGroup } from "@angular/forms"; import { debounce, map, tap } from "rxjs/operators"; import { interval, of, Subscription } from "rxjs"; @Component({ selector: "my-app", template: ` <h1>Tap Example</h1> `, styleUrls: ["./app.component.css"] }) export class AppComponent { ngOnInit() { of(1, 2, 3, 4, 5) .pipe( tap(val => { console.log("Before " + val); }), map(val => { if (val == 3) { throw Error; } return val + 5; }), tap( val => { console.log("After " + val); }, err => { console.log("Tap Error"); console.log(err); }, () => { console.log("Tap Complete"); } ) ) .subscribe(val => console.log(val)); } ngOnDestroy() {} } ***Console *** Before 1 After 6 6 Before 2 After 7 7 Before 3 Tap Error Æ’ Error() ERROR Æ’ Error() |
Reference
Read More