Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose of doOnNext(...) in RxJava

Tags:

java

rx-java

When should we use doOnNext() from Observable instead of just onNext()?

like image 917
Aravind Yarram Avatar asked Feb 09 '15 04:02

Aravind Yarram


People also ask

Why doonnext () instead of doonerror () in RxJava?

Because of its "stream" nature, is not easy to do debugging in RXJava, doOnNext () instead makes debugging easier. At this purpose you may consider also to combine it with the doOnError () operator.

What is doonnext operator in observable?

doOnNext operator called every time when source Observable emits an item. It can be used for debugging purposes, applying some action to the emitted item, logging, etc...

What is the difference between onnext and doonnext?

doOnNext is for side-effects: you want to react (eg. log) to item emissions in an intermediate step of your stream, for example before the stream is filtered, for transverse behavior like logging, but you still want the value to propagate down the stream. onNext is more final, it consumes the value.

Why is doonnext never called after subscribing?

In the example below doOnNext is never called because the source Observable emits nothing because Observable.empty () calls onCompleted after subscribing. Observable.empty () .doOnNext (item -> System.out.println ("item: " + item)) .subscribe ();


3 Answers

doOnNext is for side-effects: you want to react (eg. log) to item emissions in an intermediate step of your stream, for example before the stream is filtered, for transverse behavior like logging, but you still want the value to propagate down the stream.

onNext is more final, it consumes the value.

like image 188
Simon Baslé Avatar answered Oct 17 '22 03:10

Simon Baslé


IMPORTANT EDIT: -in bold characters immediately below-

* Once one grasps the concept, I warmly suggest you to have a look at this link, is a lifechanger, not only because we use different observable as Observable, Single, Maybe that could be need a different tool as doOnEvent() for Single and doOnEach() for Observable but because if you want to debug, there are some reasons why doOnNext() could often even not be the ideal choice, because we could ignore other events that are relevant to resolve the problem*

ORIGINAL REPLY: -partially modified-

First of all doOnNext() can be called even more times in the chain of operators between Observable and Subscribe, this gives to you greater possibilities to debug your code. Because of its "stream" nature, is not easy to do debugging in RXJava, doOnNext() instead makes debugging easier. At this purpose you may consider also to combine it with thedoOnError() operator. Why not using a simple onNext()? Because debugging is not strictly related to the logic of the code, in theory you could also eliminate the doOnNext() before to go in production.

A really essential thing to understand is that given an Observable to subscribe long chain, you can use the doOnNext in a particular point, to see what an operator is giving back to another one:

For instance :

Observable.just("Donald", "Duck", "Mickey", "Goofy",
                "Uncle")
                .doOnNext{System.out.println("Here ou will get the strings above:$it ")}
                 .map{it.length}
                 .subscribe { println("Here you will get the numbers of how every string is long: $it") }}

A typical use case to employ doOnNext() could for example occur when you want to cache a response from a server, so for instance you could use map() but also doOnNext(), because it allows you to make your code more readable as instead you would put a simple onNext() that ideally could have been structured to follow other instructions. (This is arguable, as all the architectural thoughts)

Equally to doOnNext() and for the same debugging purposes you could use others self-explanatory operators:

doOnSubscribe(), doOnUnsubscribe(), doOnCompleted(), doOnError(), doOnTerminate(),finallyDo(), doOnEach(), doOnRequest()

doOnNext() allow you to see what is going on into the Observable (often really long) chains, what is really important is that you can kinda spying what is going on trough the chain, without affecting any operation, without making any transformation( let's say not properly a kind of Log.d we use in imperative, not reactive code). This is is the reason why is called a side effect.

EDIT(because of the question in the comments):

doOnNext() and the method above are just callbacks, please refer to that, doOnNext() as the official documentation says

just modifies an Observable so that it invokes an action when it calls onNext.

Really simple, this is why is called sometimes to upload the progress bar, but also is really used in the repository pattern, for instance if you want to store data to the db/or caching after a call to retrofit for instance.

If you are really curious under the hood the doSomethingReactive methods just call the method call() ( a callback from the Interface Action) inside the "real" method SomethingReactive

like image 37
trocchietto Avatar answered Oct 17 '22 04:10

trocchietto


doOnNext() allows us to add some extra action that happens every time we get a new data item.

doOnError does not handle the error, in the sense that it does not consume one. He just does something with it, like records it. (The same is true for doOnNext - it doesn't consume the element either, and the element still ends up in the onNext Subscriber).


Observable.just("Some data...")
                .doOnNext(System.out::println)
                .doOnNext(value -> System.out.println("before transform: " + value+" You can add something here but it dont affect in data"))
                .map(value -> value + "| adding some new data")
                .doOnNext(value -> System.out.println("after transform: " + value))
                .subscribe(onNext -> {
            System.out.println("onNext: "+onNext); // print out the remaining numbers
        });

Result:

Some data...

before transform: Some data...You can add something here but it dont affect in data

after transform: Some data...| adding some new data

onNext: Some data...| adding some new data

like image 1
Arto Avatar answered Oct 17 '22 04:10

Arto