What is the rxjs tap function used for?

Nick Raphael - Oct 23 '19 - - Dev Community

Official documentation state that the tap operator will:
Perform a side effect for every emission on the source Observable, but return an Observable that is identical to the source.

Lets unpack that statement:

"Perform a side effect for every emission"

This means that everytime your observable delivers a package, your tap will fire. We kind of expected that.

"return an Observable that is identical to the source"

Now that's interesting. What this means is no matter what you do in the tap operation, it won't effect the value that gets passed to a subsequent operation. This is actually quite powerful since we can call methods outside of our ngrx flow. But in my opinion this could cause more confusion that it's worth. If I were looking at somebody elses code, I would never expect a tap to perform critical tasks. What tap is excellent for is debugging. We can console.log to see how our rxjs function stack is manipulating the data.

For example...

this.thingService
      .getThing().pipe(
        tap(object => console.log(object)),
        map(object => object.name),
        tap(name => console.log(name))
      )
      .subscribe(result => {
        ///whatever
      });
Enter fullscreen mode Exit fullscreen mode

When getThing() completes and the subscription fires, we will see a console.log of our raw value object. The map operator then changes the value to pass only the name property. And the second tap call just outputs the name. This is very useful when we have more complex rxjs pipelines and we want to see how our values change as they flow through. Really, really useful when doing switchMaps.

I'm of the opinion that using the tap operator to execute side effects is an anti-pattern. Happy to hear the opposing view.

. . . . . . . . . . . . . . . . . . . . . . . . . .