Как работают RxJava doOnError и onErrorReturn?

Я сделал эти модульные тесты, и результат не тот, который я ожидал вообще:

// This one outputs "subscribe.onError" 
@Test
public void observable_doOnError_subscribingToError() throws InterruptedException {
    Observable<String> obs = getErrorProducingObservable();
    obs.doOnError(throwable -> System.out.println("doOnError"));
    obs.subscribeOn(Schedulers.immediate()).observeOn(Schedulers.immediate()).subscribe(
        s -> {},
        error -> System.out.println("subscribe.onError")
    );
    Thread.sleep(300);
}

// This one outputs "subscribe.onError" 
@Test
public void observable_onErrorReturn() throws InterruptedException {
    Observable<String> obs = getErrorProducingObservable();
    obs.onErrorReturn(throwable -> "Yeah I got this");
    obs.subscribeOn(Schedulers.immediate()).observeOn(Schedulers.immediate()).subscribe(
        s -> System.out.println("got: " + s),
        error -> System.out.println("subscribe.onError")
    );
    Thread.sleep(300);
}

private Observable<String> getErrorProducingObservable()  {
    return Observable.create(subscriber -> {
        subscriber.onError(new RuntimeException("Somebody set up us the bomb"));
    });
}

Таким образом, оба вывода "subscribe.onError" - ни doOnError ни onErrorReturn похоже, не вызываются.

doOnError задокументирован как:

Изменяет источник Observable так, чтобы он вызывал действие, если он вызывает onError.

Я не уверен, как это сделать, но я ожидал, что выйдет "doOnError" или "doOnError", а затем "subscribe.onError".

onErrorReturn документируется как:

Поручает наблюдаемому испускать элемент (возвращенный указанной функцией) вместо вызова onError, если он обнаруживает ошибку.

Поэтому я ожидал, что "получил: да, я получил это" как результат последнего теста.

Что дает?

Ответ 1

Оба doOnError и onErrorReturn возвращают новый Observable с измененным поведением. Я согласен с тем, что их документация может немного ввести в заблуждение. Измените свои тесты таким образом, чтобы получить ожидаемое поведение:

// This one outputs "subscribe.onError" 
@Test
public void observable_doOnError_subscribingToError() throws InterruptedException {
    Observable<String> obs = 
        getErrorProducingObservable()
            .doOnError(throwable -> System.out.println("doOnError"));

    obs.subscribeOn(Schedulers.immediate()).observeOn(Schedulers.immediate()).subscribe(
        s -> {},
        error -> System.out.println("subscribe.onError")
    );
    Thread.sleep(300);
}

// This one outputs "subscribe.onError" 
@Test
public void observable_onErrorReturn() throws InterruptedException {
    Observable<String> obs = 
        getErrorProducingObservable()
            .onErrorReturn(throwable -> "Yeah I got this");

    obs.subscribeOn(Schedulers.immediate()).observeOn(Schedulers.immediate()).subscribe(
        s -> System.out.println("got: " + s),
        error -> System.out.println("subscribe.onError")
    );
    Thread.sleep(300);
}

private Observable<String> getErrorProducingObservable()  {
    return Observable.create(subscriber -> {
        subscriber.onError(new RuntimeException("Somebody set up us the bomb"));
    });
}