-
Notifications
You must be signed in to change notification settings - Fork 7.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
2.x: Update Error Handling Operators docs #6266
Changes from 2 commits
9e625ee
2039e6e
65f55ee
b9a334f
a68e6c8
0cc7585
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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) | ||
|
||
When the source reactive type signals an error event, the given `io.reactivex.functions.Consumer` is invoked. | ||
|
||
### 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("This should never be printed!"), | ||
Throwable::printStackTrace, | ||
() -> System.out.println("This should never be printed!")); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar cases below, don't want to mention them all with separate comments There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Included the "onNext" etc. in the print statements. |
||
``` | ||
|
||
## 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) | ||
|
||
When the reactive type signals an error event, the error will be swallowed and replaced by a complete event. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "by a completion event"? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed it. |
||
|
||
Optionally, a `io.reactivex.functions.Predicate` can be specified that gives more control over when an error event should be replaced by a complete event, and when not. | ||
|
||
### onErrorComplete example | ||
|
||
```java | ||
Completable.fromAction(() -> { | ||
throw new IOException(); | ||
}).onErrorComplete(error -> { | ||
// only ignore errors of type java.io.IOException | ||
lorenzpahl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return error instanceof IOException; | ||
}).subscribe( | ||
() -> System.out.println("IOException was ignored"), | ||
error -> System.err.println("This 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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inconsistency here compared to descriptions above, they started with
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd suggest to stick to one or another style There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Instructs …" is actually pretty good and concise There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have changed it to use "Instructs ..." in all descriptions. |
||
|
||
### 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("This 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("This 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("This 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason that sytnax highlighting breaks here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know why this happens (BTW this already happens in line 170; the triple backticks should also be blue). Locally, in VS Code the highlighting of the Markdown looks correct. |
||
|
||
**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) | ||
|
||
If a source reactive type emits an error, resubscribe to it 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) | ||
|
||
If a source reactive type emits an error, resubscribe to it 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) | ||
|
||
If a source reactive type emits an error, pass that 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 | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's be more clear for newcomers here with something like: "onNext should never be printed!"