i.e., by passing the error condition and not halting the entire Observable?
My Observable starts with a user-supplied list of package tracking numbers from common delivery services (FedEx, UPS, DHL, etc), looks up the expected delivery date online, then returns those dates in terms of number of days from today (i.e. "in 3 days" rather than "Jan 22"). The problem is that if any individual lookup results in an exception, the entire stream halts, and the rest of the codes won't be looked up. There's no ability to gracefully handle, say, UnknownTrackingCode Exception
, and so the Observable can't guarantee that it will look up all the codes the user submitted.
public void getDaysTillDelivery(List<String> tracking_code_list) {
Observable o = Observable.from(tracking_code_list)
// LookupDeliveryDate performs network calls to UPS, FedEx, USPS web sites or APIs
// it might throw: UnknownTrackingCode Exception, NoResponse Exception, LostPackage Exception
.map(tracking_code -> LookupDeliveryDate(tracking_code))
.map(delivery_date -> CalculateDaysFromToday(delivery_date));
o.subscribe(mySubscriber); // will handle onNext, onError, onComplete
}
Halting the Observable stream as a result of one error is by design:
- http://reactivex.io/documentation/operators/catch.html
- Handling Exceptions in Reactive Extensions without stopping sequence
- https://groups.google.com/forum/#!topic/rxjava/trm2n6S4FSc
The default behavior can be overcome, but only by eliminating many of the benefits of Rx in the first place:
- I can wrap
LookupDeliveryDate
so it returns Dates in place of Exceptions (such as1899-12-31
forUnknownTrackingCode Exception
) but this prevents "loosely coupled code", becauseCalculateDaysFromToday
would need to handle these special cases - I can surround each anonymous function with
try/catch
and blocks, but this essentially prevents me from using lambdas - I can use
if/thens
to direct the code path, but this will likely require maintaining some state and eliminating deterministic evaluation - Error handling of each step, obviously, prevents consolidating all error handling in the
Subscriber
- Writing my own error-handling operator is possible, but thinly documented
Is there a better way to handle this?