What is the difference between tap and map in RxJS?
A mapping function takes a thing and returns another thing. e.g. I can build a function that takes 10
and returns 11
, that takes 11
and returns 12
, etc.
const inc = n => n + 1;
Array#map
applies such mapping function to all elements of an array but "map" doesn't mean "iteration".
In RxJS, when a data is sent to the stream it goes through a series of operators:
- The
map
operator will simply apply a function to that data and return the result. - The
tap
operator however takes a data, apply a function to that data but returns the original data, if the function bothered to return a result,tap
just ignores it.
Here's an example:
- We push
10
to streama$
,tap
just log the value. We know thatconsole.log
always returnundefined
but that's fine becausetap
simply returns its parameter. - We push
10
to streamb$
, it goes throughmap(inc)
which appliesinc
to10
returning11
.
const a$ = of(10).pipe(tap(n => console.log(`tap: ${n}`)));
const b$ = of(10).pipe(map(inc));
a$.subscribe(n => console.log(`n from a$: ${n}`));
b$.subscribe(n => console.log(`n from b$: ${n}`));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.min.js"></script>
<script>
const {of} = rxjs;
const {map, tap} = rxjs.operators;
const inc = n => n + 1;
</script>
The purpose of
tap
is to execute an action keeping the same value of the observableThe purpose of
map
is to transform the emitted values of the observable
const messagesCount$ = newMessages$
.pipe(tap(messages => notificationService.notify('You have ' + message.length + ' message(s)')))
.pipe(map(messages => messages.length))
Tap should be Used for Notification, logging non-contextual/critical side effects.
It's like a "peek" into the "pipe". The data stays the same, You can do something with it. Some data goes in, you look, same data comes out.
Map is for transformation/mapping of the Data in the "pipe". Some data comes in, different/transformed data comes out.