-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
2.x: Update Error Handling Operators docs (#6266)
* Change document structure; update operator list * Add examples * Clarify which handler is invoked * Use consistent wording in the descriptions * Cleanup
- Loading branch information
1 parent
feb6db7
commit fba8b61
Showing
1 changed file
with
277 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,284 @@ | ||
There are a variety of operators that you can use to react to or recover from `onError` notifications from Observables. For example, you might: | ||
There are a variety of operators that you can use to react to or recover from `onError` notifications from reactive sources, such as `Observable`s. For example, you might: | ||
|
||
1. swallow the error and switch over to a backup Observable to continue the sequence | ||
1. swallow the error and emit a default item | ||
1. swallow the error and immediately try to restart the failed Observable | ||
1. swallow the error and try to restart the failed Observable after some back-off interval | ||
|
||
The following pages explain these operators. | ||
# Outline | ||
|
||
* [**`onErrorResumeNext( )`**](http://reactivex.io/documentation/operators/catch.html) — instructs an Observable to emit a sequence of items if it encounters an error | ||
* [**`onErrorReturn( )`**](http://reactivex.io/documentation/operators/catch.html) — instructs an Observable to emit a particular item when it encounters an error | ||
* [**`onExceptionResumeNext( )`**](http://reactivex.io/documentation/operators/catch.html) — instructs an Observable to continue emitting items after it encounters an exception (but not another variety of throwable) | ||
* [**`retry( )`**](http://reactivex.io/documentation/operators/retry.html) — if a source Observable emits an error, resubscribe to it in the hopes that it will complete without error | ||
* [**`retryWhen( )`**](http://reactivex.io/documentation/operators/retry.html) — if a source Observable emits an error, pass that error to another Observable to determine whether to resubscribe to the source | ||
- [`doOnError`](#doonerror) | ||
- [`onErrorComplete`](#onerrorcomplete) | ||
- [`onErrorResumeNext`](#onerrorresumenext) | ||
- [`onErrorReturn`](#onerrorreturn) | ||
- [`onErrorReturnItem`](#onerrorreturnitem) | ||
- [`onExceptionResumeNext`](#onexceptionresumenext) | ||
- [`retry`](#retry) | ||
- [`retryUntil`](#retryuntil) | ||
- [`retryWhen`](#retrywhen) | ||
|
||
## doOnError | ||
|
||
**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Completable` | ||
|
||
**ReactiveX documentation:** [http://reactivex.io/documentation/operators/do.html](http://reactivex.io/documentation/operators/do.html) | ||
|
||
Instructs a reactive type to invoke the given `io.reactivex.functions.Consumer` when it encounters an error. | ||
|
||
### doOnError example | ||
|
||
```java | ||
Observable.error(new IOException("Something went wrong")) | ||
.doOnError(error -> System.err.println("The error message is: " + error.getMessage())) | ||
.subscribe( | ||
x -> System.out.println("onNext should never be printed!"), | ||
Throwable::printStackTrace, | ||
() -> System.out.println("onComplete should never be printed!")); | ||
``` | ||
|
||
## onErrorComplete | ||
|
||
**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Completable` | ||
|
||
**ReactiveX documentation:** [http://reactivex.io/documentation/operators/catch.html](http://reactivex.io/documentation/operators/catch.html) | ||
|
||
Instructs a reactive type to swallow an error event and replace it by a completion event. | ||
|
||
Optionally, a `io.reactivex.functions.Predicate` can be specified that gives more control over when an error event should be replaced by a completion event, and when not. | ||
|
||
### onErrorComplete example | ||
|
||
```java | ||
Completable.fromAction(() -> { | ||
throw new IOException(); | ||
}).onErrorComplete(error -> { | ||
// Only ignore errors of type java.io.IOException. | ||
return error instanceof IOException; | ||
}).subscribe( | ||
() -> System.out.println("IOException was ignored"), | ||
error -> System.err.println("onError should not be printed!")); | ||
``` | ||
|
||
## onErrorResumeNext | ||
|
||
**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Completable` | ||
|
||
**ReactiveX documentation:** [http://reactivex.io/documentation/operators/catch.html](http://reactivex.io/documentation/operators/catch.html) | ||
|
||
Instructs a reactive type to emit a sequence of items if it encounters an error. | ||
|
||
### onErrorResumeNext example | ||
|
||
```java | ||
Observable<Integer> numbers = Observable.generate(() -> 1, (state, emitter) -> { | ||
emitter.onNext(state); | ||
|
||
return state + 1; | ||
}); | ||
|
||
numbers.scan(Math::multiplyExact) | ||
.onErrorResumeNext(Observable.empty()) | ||
.subscribe( | ||
System.out::println, | ||
error -> System.err.println("onError should not be printed!")); | ||
|
||
// prints: | ||
// 1 | ||
// 2 | ||
// 6 | ||
// 24 | ||
// 120 | ||
// 720 | ||
// 5040 | ||
// 40320 | ||
// 362880 | ||
// 3628800 | ||
// 39916800 | ||
// 479001600 | ||
``` | ||
|
||
## onErrorReturn | ||
|
||
**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Completable` | ||
|
||
**ReactiveX documentation:** [http://reactivex.io/documentation/operators/catch.html](http://reactivex.io/documentation/operators/catch.html) | ||
|
||
Instructs a reactive type to emit the item returned by the specified `io.reactivex.functions.Function` when it encounters an error. | ||
|
||
### onErrorReturn example | ||
|
||
```java | ||
Single.just("2A") | ||
.map(v -> Integer.parseInt(v, 10)) | ||
.onErrorReturn(error -> { | ||
if (error instanceof NumberFormatException) return 0; | ||
else throw new IllegalArgumentException(); | ||
}) | ||
.subscribe( | ||
System.out::println, | ||
error -> System.err.println("onError should not be printed!")); | ||
|
||
// prints 0 | ||
``` | ||
|
||
## onErrorReturnItem | ||
|
||
**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Completable` | ||
|
||
**ReactiveX documentation:** [http://reactivex.io/documentation/operators/catch.html](http://reactivex.io/documentation/operators/catch.html) | ||
|
||
Instructs a reactive type to emit a particular item when it encounters an error. | ||
|
||
### onErrorReturnItem example | ||
|
||
```java | ||
Single.just("2A") | ||
.map(v -> Integer.parseInt(v, 10)) | ||
.onErrorReturnItem(0) | ||
.subscribe( | ||
System.out::println, | ||
error -> System.err.println("onError should not be printed!")); | ||
|
||
// prints 0 | ||
``` | ||
|
||
## onExceptionResumeNext | ||
|
||
**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Completable` | ||
|
||
**ReactiveX documentation:** [http://reactivex.io/documentation/operators/catch.html](http://reactivex.io/documentation/operators/catch.html) | ||
|
||
Instructs a reactive type to continue emitting items after it encounters an `java.lang.Exception`. Unlike [`onErrorResumeNext`](#onerrorresumenext), this one lets other types of `Throwable` continue through. | ||
|
||
### onExceptionResumeNext example | ||
|
||
```java | ||
Observable<String> exception = Observable.<String>error(IOException::new) | ||
.onExceptionResumeNext(Observable.just("This value will be used to recover from the IOException")); | ||
|
||
Observable<String> error = Observable.<String>error(Error::new) | ||
.onExceptionResumeNext(Observable.just("This value will not be used")); | ||
|
||
Observable.concat(exception, error) | ||
.subscribe( | ||
message -> System.out.println("onNext: " + message), | ||
err -> System.err.println("onError: " + err)); | ||
|
||
// prints: | ||
// onNext: This value will be used to recover from the IOException | ||
// onError: java.lang.Error | ||
``` | ||
|
||
## retry | ||
|
||
**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Completable` | ||
|
||
**ReactiveX documentation:** [http://reactivex.io/documentation/operators/retry.html](http://reactivex.io/documentation/operators/retry.html) | ||
|
||
Instructs a reactive type to resubscribe to the source reactive type if it encounters an error in the hopes that it will complete without error. | ||
|
||
### retry example | ||
|
||
```java | ||
Observable<Long> source = Observable.interval(0, 1, TimeUnit.SECONDS) | ||
.flatMap(x -> { | ||
if (x >= 2) return Observable.error(new IOException("Something went wrong!")); | ||
else return Observable.just(x); | ||
}); | ||
|
||
source.retry((retryCount, error) -> retryCount < 3) | ||
.blockingSubscribe( | ||
x -> System.out.println("onNext: " + x), | ||
error -> System.err.println("onError: " + error.getMessage())); | ||
|
||
// prints: | ||
// onNext: 0 | ||
// onNext: 1 | ||
// onNext: 0 | ||
// onNext: 1 | ||
// onNext: 0 | ||
// onNext: 1 | ||
// onError: Something went wrong! | ||
``` | ||
|
||
## retryUntil | ||
|
||
**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_off.png) `Completable` | ||
|
||
**ReactiveX documentation:** [http://reactivex.io/documentation/operators/retry.html](http://reactivex.io/documentation/operators/retry.html) | ||
|
||
Instructs a reactive type to resubscribe to the source reactive type if it encounters an error until the given `io.reactivex.functions.BooleanSupplier` returns `true`. | ||
|
||
### retryUntil example | ||
|
||
```java | ||
LongAdder errorCounter = new LongAdder(); | ||
Observable<Long> source = Observable.interval(0, 1, TimeUnit.SECONDS) | ||
.flatMap(x -> { | ||
if (x >= 2) return Observable.error(new IOException("Something went wrong!")); | ||
else return Observable.just(x); | ||
}) | ||
.doOnError((error) -> errorCounter.increment()); | ||
|
||
source.retryUntil(() -> errorCounter.intValue() >= 3) | ||
.blockingSubscribe( | ||
x -> System.out.println("onNext: " + x), | ||
error -> System.err.println("onError: " + error.getMessage())); | ||
|
||
// prints: | ||
// onNext: 0 | ||
// onNext: 1 | ||
// onNext: 0 | ||
// onNext: 1 | ||
// onNext: 0 | ||
// onNext: 1 | ||
// onError: Something went wrong! | ||
``` | ||
|
||
## retryWhen | ||
|
||
**Available in:** ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Flowable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Observable`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Maybe`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Single`, ![image](https://raw.github.com/wiki/ReactiveX/RxJava/images/checkmark_on.png) `Completable` | ||
|
||
**ReactiveX documentation:** [http://reactivex.io/documentation/operators/retry.html](http://reactivex.io/documentation/operators/retry.html) | ||
|
||
Instructs a reactive type to pass any error to another `Observable` or `Flowable` to determine whether to resubscribe to the source. | ||
|
||
### retryWhen example | ||
|
||
```java | ||
Observable<Long> source = Observable.interval(0, 1, TimeUnit.SECONDS) | ||
.flatMap(x -> { | ||
if (x >= 2) return Observable.error(new IOException("Something went wrong!")); | ||
else return Observable.just(x); | ||
}); | ||
|
||
source.retryWhen(errors -> { | ||
return errors.map(error -> 1) | ||
|
||
// Count the number of errors. | ||
.scan(Math::addExact) | ||
|
||
.doOnNext(errorCount -> System.out.println("No. of errors: " + errorCount)) | ||
|
||
// Limit the maximum number of retries. | ||
.takeWhile(errorCount -> errorCount < 3) | ||
|
||
// Signal resubscribe event after some delay. | ||
.flatMapSingle(errorCount -> Single.timer(errorCount, TimeUnit.SECONDS)); | ||
}).blockingSubscribe( | ||
x -> System.out.println("onNext: " + x), | ||
Throwable::printStackTrace, | ||
() -> System.out.println("onComplete")); | ||
|
||
// prints: | ||
// onNext: 0 | ||
// onNext: 1 | ||
// No. of errors: 1 | ||
// onNext: 0 | ||
// onNext: 1 | ||
// No. of errors: 2 | ||
// onNext: 0 | ||
// onNext: 1 | ||
// No. of errors: 3 | ||
// onComplete | ||
``` |