Skip to content

Commit 055dc2c

Browse files
committed
3.3 Added retryWhen
1 parent db149ef commit 055dc2c

File tree

1 file changed

+38
-0
lines changed

1 file changed

+38
-0
lines changed

Part 3 - Taming the sequence/3. Advanced error handling.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,44 @@ Here. we've specified that we want to retry once. Our observable fails after two
126126

127127
In this example, we have done something naughty: we have made our subscription stateful to demonstrate that the observable is restarted from the source. The observable produced different values the second time around. `retry` does not cache any elements like `replay`, nor would it make sense to do so. It will become apparent why this matters once we discuss the differences between hot and cold observables.
128128

129+
### retryWhen
130+
131+
`retry` will restart the subscription as soon as the failure happens. If we need more control over this, we can use `retryWhen`.
132+
133+
```java
134+
public final Observable<T> retryWhen(Func1<? super Observable<? extends java.lang.Throwable>,? extends Observable<?>> notificationHandler)
135+
```
136+
137+
The argument to `retryWhen` is a function that takes an observable and returns another. The input observable emits all the errors that `retryWhen` encounters. The resulting observable signals when to retry:
138+
* if it emits a value, `retryWhen` will retry,
139+
* if it terminates, `retryWhen` will emit the error and not retry.
140+
Note that the type of the signaling obserable of the actual values emitted don't matter. The values are discarded and the observable is only used for timing.
141+
142+
In the next example, we will construct a retrying policy where we wait 100ms before retrying.
143+
144+
```java
145+
Observable<Integer> source = Observable.create(o -> {
146+
o.onNext(1);
147+
o.onNext(2);
148+
o.onError(new Exception("Failed"));
149+
});
150+
151+
source.retryWhen((o) -> o.take(2).delay(100, TimeUnit.MILLISECONDS))
152+
.timeInterval()
153+
.subscribe(System.out::println);
154+
```
155+
Output
156+
```
157+
TimeInterval [intervalInMilliseconds=17, value=1]
158+
TimeInterval [intervalInMilliseconds=0, value=2]
159+
TimeInterval [intervalInMilliseconds=102, value=1]
160+
TimeInterval [intervalInMilliseconds=0, value=2]
161+
TimeInterval [intervalInMilliseconds=102, value=1]
162+
TimeInterval [intervalInMilliseconds=0, value=2]
163+
```
164+
165+
Our source observable emits 2 values and immediately fails. When that happens, the observable of failures inside `retryWhen` emits the error. We delay that emission by 100ms and send it back to signal to retry. `take(2)` guarantees that our signaling observabe will terminate after we receive two errors. That means that `retryWhen` won't retry after 2 failures.
166+
129167
## using
130168

131169
The `using` operator is for creating observables from resources that need to managed. It guarantees that your resources will be managed regardless of when and how subscriptions are terminated. If you were to just use `create`, you would have to do the managing in the traditional Java paradigm and inject it into Rx. `using` is a more natural way of managing you resources in Rx.

0 commit comments

Comments
 (0)