theblang
theblang

Reputation: 10425

Short-circuit a flatMap if an exception occurs

I have a flatMap that runs a series of HTTP calls to register a user, retrieve their profile, and some other things. I would like to notify onError in my subscription with a particular error message depending on which stage of the flatMap an error occurs. Maybe the registration was successful, but retrieving the created profile was not. How could I accomplish this such that my flatMap stops all the subsequent calls once an error happens?

Here is some pseudocode of my Observable and Subscription:

Retrofit.registerUser()
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .flatMap({
            return Retrofit.authenticate();
        })
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .flatMap({
            return Retrofit.retrieveProfile() 
        })
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .flatMap({
            return Retrofit.retrieveOtherStuff()
        })
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1 {

        }, new Action1<Throwable>() {
          // I would like to display the error to my user here
        }));

Upvotes: 1

Views: 1171

Answers (1)

Vladimir Mironov
Vladimir Mironov

Reputation: 30874

There are at least two ways to do it:

  1. Using doOnError operator:

    Retrofit.registerUser()
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .doOnError(error -> {
            showRegistrationFailedError(error);
        })
        .flatMap({
            return Retrofit.authenticate().doOnError(error -> {
                showAuthenticationFailedError(error);
            });
        })
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1 {
    
        }, new Action1<Throwable>() {
          // do nothing here. all errors are already handled in doOnError methods
        }));
    
  2. Using onErrorResumeNext operator:

    Retrofit.registerUser()
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .onErrorResumeNext(error -> {
            return Observable.error(new RegistrationFailedException(error));
        })
        .flatMap({
            return Retrofit.authenticate().onErrorResumeNext(error -> {
                return Observable.error(new AuthenticationFailedException(error))
            });
        })
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(value -> {
    
        }, error -> {
            if (error instanceof RegistrationFailedException) {
                showRegistrationFailedError(error);
            }
    
            if (error instanceof AuthenticationFailedException) {
                showAuthenticationFailedError(error);   
            }
        }));
    

Upvotes: 1

Related Questions