问题
Asume we have two observables A
and B
. A
publishes a result certainly, while the result from B
might not be published at all (timeout).
The question is how to map the result from A
and B
if B
returns within a timeframe, otherwise just return the result from A
.
Observable<DatabaseObject> A = getDatabaseElement();
Observable<NetworkObject> B = restApi.getElement();
Map example:
map((databaseObject, networkObject) => {
databaseObject.setData(networkObject);
return databaseObject;
})
回答1:
In order to timeout B
observable use take
operator with time argument:
B.take(10, TimeUnit.SECONDS)
In order to receive either A
or B
(if B
is ready within timeout) use concatWith
:
A.concatWith(B.take(10, TimeUnit.SECONDS))
.takeLast(1)
In case you wish to combine A
and B
(optionally enrich A
with B
):
A.concatWith(B.take(10, TimeUnit.SECONDS))
.reduce((a, b) -> a.setData(b))
In case A
and B
are of different types (optionally enrich A
with B
):
Observable.combineLatest(
A,
B.take(10, TimeUnit.SECONDS).defaultIfEmpty(stubB)),
(a, b) -> { if (b != stubB) a.setData(b); }
)
回答2:
You might want to take a different approach here .. There is an operator designed exactly for the behavior you described. Take a look at .timeout(long time, TimeUnits units, Observable backupObservable)
which instructs a stream to switch from the original observable (in your case B, the network request I assume) to the backup A observable when there are no other items in the original stream for the specified amount of time.
来源:https://stackoverflow.com/questions/41762526/rxjava-combine-observable-with-another-optional-observable-with-timeout