What is the difference between map and doOnNext in flux? (i.e project reactor)
Asked Answered
L

2

16

In Flux map function is also executed for each item in the flux. For doOnNext function is also executed for every item (emitted) in the flux. What is the difference from the user's perspective? Why do two similar methods exist? Could someone explain with a simple use-case?

Lifelike answered 6/2, 2020 at 20:39 Comment(0)
S
18

TLDR; Flux#doOnNext is for side effects, Flux#map is for mapping something from one type to another type, synchronously.

If we look at the documentation it says the following for doOnNext

Flux<T> doOnNext(Consumer<? super T> onNext)
Add behavior (side-effect) triggered when the Flux emits an item.

this means in doOnNext, we can do side effects, like log, or do a rest call somewhere etc. etc. We also return a Flux of type T, that is the same that doOnNext is taking in, so no type change.

If we on the other hand look at Map:

Flux<V> map(Function<? super T,? extends V> mapper)
Transform the items emitted by this Flux by applying a synchronous function to 
each item.

We can read that here we can apply a synchronous function, basically we can do something with our emitted value. Add something, deduct something, change it some way, here we can transform it, for instance map it to something else.

If we look at the types in map, we can see that map will emit something super T but it will return something that extends V

This is a typical Java generics pattern and if you wish to know more about just this, I recommend you watch Joshua Blochs talk about generics. The entire video is a good watch and will explain it much better than me.

But what I want to point out is that by using map, you are returning a different type. You get something that super T from the flux, you then map it to something else that extends V.

Schutz answered 6/2, 2020 at 23:32 Comment(3)
Thanks for the response. The map function can do "what doOnNext function can do". what i s the functionality doOnNext function can do, the map function can't do?Lifelike
it does not consume the items, map function doesSchutz
IMO, doOnNext provides immutability of the received input. In map you don't.Ediva
T
18

Just to add to the other nice answer - I think the one important part that I was missing when I started using doOnNext() is that it is not a "consumer" counter-part of "function-like" map and flatMap.

doOnNext is sort of a callback that gets executed when a Publisher emits an item but it does not affect the flow, namely it returns the original Publisher immediately.
Example: initially I thought I could do things like

Mono.from()
    .doOnNext(doSomethingConsumer)
    .doOnNext(thenDoSomethingElseConsumer);

when I am not interested in the return value and that these things will be applied in order.
This is completely wrong! In fact, both doOnNext() operators are applied immediately.

Tremblay answered 4/11, 2020 at 13:52 Comment(2)
What was the correct way to do what you wanted?Keefer
I tried running 2 doOnNext. 1 with a sleep, the two didn't get executed parallely. 2nd doOnNext waited for completion of the 1st doOnNext. So they are kind of applied in order? gist.github.com/asthinasthi/5d3cc12e853449063a0e0a724e704b4aEdiva

© 2022 - 2024 — McMap. All rights reserved.