-
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 all 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) | ||
|
||
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 | ||
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) | ||
|
||
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 | ||
``` |
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.
Inconsistency here compared to descriptions above, they started with
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.
I'd suggest to stick to one or another style
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.
"Instructs …" is actually pretty good and concise
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.
I have changed it to use "Instructs ..." in all descriptions.