If you’ve worked with RxJava/RxKotlin, you might be familiar with three methods of a subscriber. onNext , onError and onComplete. In a reactive stream, elements are consumed by onNext first, and onComplete is called when the stream ends. If you encounter any error in onNext, the complete observable chain is abandoned and control is shifted to onError method. So for example, the below code will run perfectly and will provide the output as:
Now suppose we encounter an exception in onNext, the whole observable chain is dropped. In the below code, we will deliberately induce an exception when the input is 2:
Exception on 2
This is all well and good if you encounter an error in subscriber, but what if you encounter an error in one of the operators above it? It could be in map operator, or in flatMap operator. The point is, what to do if you encounter an error before it makes its way to the subscriber? There are so many things that we can do in RxJava if we encounter an error. The first one we will be talking about is onExceptionResumeNext():
To understand this one, we need to know about doOnNext first. You might be thinking, it sounds much like onNext of a subscriber. That’s right! doOnNext is basically for side-effects. The items will go to doOnNext before it gets finally consumed by onNext method of the observer. So doOnNext is a great place for debugging your items in the stream. Now back to onExceptionResumeNext, if we encounter any exception in the observable chain(before they make their way to the observer methods), we can use this method to plug in another
observable. Let’s have a look at the below code:
In the above code, we deliberately induced an exception when the item is 2 (before it makes it way to get consumed by the observer) in the doOnNext and when the exception is triggered we plugged in another observable Observable.just(10) and that starts another stream of items, which gets consumed by the previous observer.
One of the use cases of this can be a fall back mechanism. Suppose you want to get the latest news from an API and if there is an error (suppose network connection is down), you can plug in an observable that takes data from your local database. This way, you are still showing news (even though it is stale).
It is quite similar to the onExceptionResumeNext but it is for general error. The onExceptionResumeNext handles throwables of the java.lang.Exception and onErrorResumeNext can handle error of type java.lang.Throwable and java.lang.Error. Checkout the below image that describe its working
This is quite similar to doOnNext in the way since it can be used to intercept the error before the error makes its way to the consumer. Let’s have a look at the below example:
Doing on error
Exception on 2
So as you can see, the block doOnError was run before the onError of the observer. So it’s a great place to do some stuff incase you are about to receive an error. This could include showing toast message or snackbar informing about error.
As the name suggests, it just returns a value if an error is encountered. Let’s see the below example:
As you can see, after encountering an error, it returns “-1”. The placing of onErrorReturnItem is crucial. It needs to be downstream from where the error occurs.So in the above example, if you had placed onErrorReturnItem before doOnNext, it wouldn’t have returned the “-1”.
Sometimes, you need to produce the default item (in case you encounter an error) dynamically. So onErrorReturn provides you throwable and a lambda, which you can use to determine the value you want to return.
Similar to onErrorReturnItem, position of onErrorReturn also matters. It needs to be downstream of the error in order to fall into onErrorReturn lambda.
This is another way of error handling. It simply resubscribes the preceding Observable. You need to take care while using this operator. Let’s take a previous example here with retry operator:
As you can see, it went into an infinite loop since the retry operator is resubscribing to the Observable which is getting an exception at “2”.
To overcome this situation, you can also provide a number and the retry attempt will be reduced to that fixed number. It can be done as below:
Doing this will reduce the retry attempt to 3. There are other variations like retryUntil, retryWhen which are quite similar so you can read more on that at http://reactivex.io/documentation/operators/retry.html
PS: I’ve made this simple free Android app that helps you maintain consistency toward your goals based on the technologies/tools mentioned above. Feel free to check it out:
If you like this article, please share it and put a Clap on it. Also, you can follow me by clicking on the below link.
If you like it then put a clap (👏 ) on it.
Here are the other articles about RxJava by me which you might enjoy -
RxJava - Flowables - What, when and how to use it? - Aanand Shekhar Roy
RxJava - Flowables - What, when and how to use it?
- Aanand Shekhar Roy RxJava - Flowables - What, when and how to use it?www.aanandshekharroy.com