14

I am just getting started with RxJava, but maybe something did not click yet.

1.

Integer[] items = {1, 2, 3, 0, 0, 4, 5, 6, 1};
Observable.from(items)
        .map(this::invert)
        .subscribe(i -> Log.d(LOG_TAG, "Inverted: " + i), t -> Log.d(LOG_TAG, "Error: " + t.getMessage()));

2.

Integer[] items = {1, 2, 3, 0, 0, 4, 5, 6, 1};
Observable.from(items)
        .map(this::invert)
        .doOnError(t -> Log.d(LOG_TAG, "Error: " + t.getMessage()))
        .doOnNext(i -> Log.d(LOG_TAG, "Inverted: " + i))
        .subscribe();

The invert function:

int invert(int i) {
    return 1 / i;
}

The first executes normally, and when the exception is thrown the onError is executed. But on the other hand, the second does not work, so the exception is thrown all the way up to the calling method.

What is the difference between the two blocks of code?

thyago stall
  • 1,654
  • 3
  • 16
  • 30

2 Answers2

25

Keep in mind that .doOnError() catches the exception, does something with it and then re-throws it. If you want different behavior, use one of the .onError* methods.

Now, the reason why the exception does not propagate to the caller in #1 but does in #2 is that you've provided an error handler in #1, but not in #2, in which case the default is to propagate the exception.

Tassos Bassoukos
  • 16,017
  • 2
  • 36
  • 40
0

To complete Tassos's answer:

RxJava does not allow exception 'bubbling'. If an exception escapes the execution chain without getting caught, rather than propagate it up to your calling code, Rx will catch it and log an error message like onErrorDropped reactor.core.Exceptions$ErrorCallbackNotImplemented: <your exeception and message here>. See https://github.com/reactor/reactor-core/issues/2677

As Tassos said, the exception is rethrown from doOnError(). So if you use this functionality for error handling, you should remove the error from the chain, like so

Observable.from(items)
    .map(this::invert)
    .doOnError(t -> Log.d(LOG_TAG, "Error: " + t.getMessage()))
    .onErrorResume(e -> Mono.empty()) // Replace Mono.empty() with an alternative function if you want some behavior on error
    .doOnNext(i -> Log.d(LOG_TAG, "Inverted: " + i))
    .subscribe();

See https://nickolasfisher.com/blog/Making-Sense-of-Mono-Error-Handling-in-Spring-Boot-WebfluxProject-Reactor for more details on how that onErrorX works

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Tadhg
  • 561
  • 5
  • 15