0

I have a case in my app where I want to fetch from multiple sources and return first valid data. I'd think .concatDelayArray() and .first() would be valid choices for this, but using them causes a crash if any of the non-last Singles throw an error.

Here's my test case:

Single<String> first = Single.fromCallable(() -> {
    throw new Exception("Random exception");
});
Single<String> second = Single.fromCallable(() -> "");
Single<String> third = Single.fromCallable(() -> "value");

Single.concatArrayDelayError(first, second, third)
    .filter(value -> !value.isEmpty())
    .firstOrError()
    .test()
    .assertValue("value");      

This ends with a crash:

io.reactivex.rxjava3.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with.

Is there a better operator for this case?

Tomislav Turcic
  • 879
  • 1
  • 11
  • 24
  • 1
    You could look into `Single.amb()` or use `Single.merge(...).firstOrError()` – Sergej Isbrecht Dec 17 '20 at 12:09
  • Problem with .amb() is that the stream will terminate if any Single throws an error. Problem with merge is that it will subscribe to all Singles and I don't want that. If the first Single returns valid data, no other sources should be subscribed to. – Tomislav Turcic Dec 17 '20 at 12:25
  • 2
    You could suppress the error via `onErrorReturnItem` on each source. You could also turn the sources into `Maybe`s and use `onErrorComplete` in case there is no good default value. Third, you could just install a global error handler as the [link](https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling) in the actual error message points out. – akarnokd Dec 17 '20 at 12:31
  • Cool, thanks. I was hoping there would be a way to do this without onErrorReturnItem, but since Rx2+ doesn't allow error swallowing, this happens. – Tomislav Turcic Dec 17 '20 at 13:57

0 Answers0