Reputation: 28545
I have code that invokes 2 apis and merges the results. using retrofit and rxJava.
How can I handle it so that if there is a problem with one of the api's i can still get the result from one of the api's that did work?
IPlaces api = adapter.create(IPlaces.class); //endpoint1
IPlaces api2 = adapter2.create(IPlaces.class); //endpoint2
Observable.combineLatest(
api.getPlacesFrom1("key", placeId),
api2.getPlacesFrom2(placeId),
new Func2<PlaceDetailResult1, PlaceDetailResult2, MergedReviews>() {
@Override
public MergedReviews call(PlaceDetailResult placeDetailResult1, PlaceDetailResult2 placeDetailResult2) {
// processToMerge( placeDetailResult1, placeDetailResult2)
return mr;
}
})
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<MergedReviews>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(MergedReviews mr) {
SetAdapter(mr.reviews);
SetPhotosAdapter(mr.photos);
}
});
Upvotes: 2
Views: 1944
Reputation: 621
As outlined in the comments, you can transform exceptions into null
objects (or any other object) using onError*
.
Here is a minimal example which I believe captures your setting. It takes two integer observables which provide one Integer
value and combines them in some way. If one of the observables yields an error the other value is transmitted, if both yield an error a RuntimeException
is thrown. I use zipWith
instead of combineLatest
since this is sufficient for your case where exactly one value is expected from each of the two observables.
Observable<Integer> zipThrowing(Observable<Integer> observable1, Observable<Integer> observable2) {
return observable1.onErrorReturn(ex-> null)
.zipWith(observable2.onErrorReturn(ex->null),
(a,b)->{
if(b == null) {
if(a==null){
throw new RuntimeException("None of the two values are valid.");
}
return a;
}
if(a==null) {
return b;
}
return a+b;
}
);
Transforming exceptions into null
values may be unacceptable in some cases. If you need the information in your exception I suggest you use a result object containing either the actual value or the exception.
Upvotes: 2