web-dev-qa-db-fra.com

Comment fonctionnent RxJava doOnError et onErrorReturn?

J'ai fait ces tests unitaires, et le résultat n'est pas du tout ce à quoi je m'attendais:

// 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"));
    });
}

Donc, les deux sorties "subscribe.onError" - ni doOnError ni onErrorReturn ne semblent être appelées.

doOnError est documenté comme:

Modifie l'Observable source afin qu'il invoque une action s'il appelle onError.

Je ne sais pas comment interpréter cela, mais je m'attendais à ce que "doOnError" soit sorti ou "doOnError" suivi de "subscribe.onError".

onErrorReturn est documenté comme:

Demande à un observable d'émettre un élément (retourné par une fonction spécifiée) plutôt que d'appeler onError s'il rencontre une erreur.

Par conséquent, je m'attendais à "got: Yeah I got this" comme sortie de ce dernier test.

Ce qui donne?

20
Nilzor

doOnError et onErrorReturn renvoient un nouveau Observable avec le comportement modifié. Je conviens que leur documentation peut être un peu trompeuse. Modifiez vos tests comme ceci pour obtenir le comportement attendu:

// 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"));
    });
}
16
marstran