【问题标题】:How to change parameters in retry request after error in RxJavaRxJava出错后如何更改重试请求中的参数
【发布时间】:2017-01-15 20:05:43
【问题描述】:

我使用改造 2.0 向服务器发送登录请求,服务器返回客户端会话令牌,我必须在其他请求中使用它,但是这个令牌的生命周期有限,当它过期时服务器返回 HTTP 错误 401 .

在收到此错误后,我尝试重新登录,并在下一个代码的帮助下:

    holder.getApi(GuideProfileApi.class)
      .getProfile(String.valueOf(holder.getServerId()), holder.getServerToken())
      .subscribeOn(Schedulers.io())
      .retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {
         @Override
         public ObservableSource<?> apply(Observable<Throwable> throwableObservable) throws Exception {
           return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {
             @Override
             public ObservableSource<?> apply(Throwable throwable) throws Exception {
               if (throwable instanceof HttpException &&  ((HttpException)throwable).code() == 401) {
                 RegistryLoginResult loginResult = holder.login().blockingSingle();
                 return holder.getApi(GuideProfileApi.class)
                    .getProfile(String.valueOf(loginResult.getUserId()), loginResult.getSessionToken());
               }
               return Observable.error(throwable);
            }
        });
     }
  })
  .observeOn(AndroidSchedulers.mainThread())
  .subscribe(new Consumer<ProfileResult>() {
    @Override
    public void accept(ProfileResult profileResult) throws Exception {
      Log.d("Result", profileResult.toString());
    }
  }, new Consumer<Throwable>() {
      @Override
      public void accept(Throwable throwable) throws Exception {
        Log.e("Result", throwable.getLocalizedMessage());
      }
});

并发送重试请求,但请求参数与错误请求相同(重新登录之前)。如何在再次发送之前更改请求的参数?

【问题讨论】:

    标签: android retrofit2 rx-java2


    【解决方案1】:

    你可以使用retryWhen,但问题是你的 retryWhen 重试了你在惰性时刻创建的同一个 observable 对象。 您的解决方案是使用运算符 defer 来获取 host(),因为 defer 不是在您定义它时创建 observable,而是在它被订阅者消费时创建。

    Observable.defer(()-> holder.getApi(GuideProfileApi.class)
              .getProfile(String.valueOf(holder.getServerId()),holder.getServerToken()))
      .subscribeOn(Schedulers.io())
      .retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {
         @Override
         public ObservableSource<?> apply(Observable<Throwable> throwableObservable) throws Exception {
           return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {
             @Override
             public ObservableSource<?> apply(Throwable throwable) throws Exception {
               if (throwable instanceof HttpException &&  ((HttpException)throwable).code() == 401) {
                 RegistryLoginResult loginResult = holder.login().blockingSingle();
                 return holder.getApi(GuideProfileApi.class)
                    .getProfile(String.valueOf(loginResult.getUserId()), loginResult.getSessionToken());
               }
               return Observable.error(throwable);
            }
        });
     }
      })
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(new Consumer<ProfileResult>() {
        @Override
        public void accept(ProfileResult profileResult) throws Exception {
          Log.d("Result", profileResult.toString());
        }
          }, new Consumer<Throwable>() {
              @Override
              public void accept(Throwable throwable) throws Exception {
                Log.e("Result", throwable.getLocalizedMessage());
              }
        });
    

    你可以在这里看到一些重试的例子https://github.com/politrons/reactive/blob/master/src/test/java/rx/observables/errors/ObservableExceptions.java

    【讨论】:

      【解决方案2】:

      您使用了错误的运算符。如果遇到错误,retryWhen 将重试您的原始可观察对象。你需要的是onErrorResumeNext。类似的东西

       holder.getApi(GuideProfileApi.class)
            .getProfile(String.valueOf(holder.getServerId()), holder.getServerToken())
            .subscribeOn(Schedulers.io())
            .onErrorResumeNext(new Function<Throwable, ObservableSource<?>>() {
              @Override
               public ObservableSource<?> apply(Throwable throwable) {
                     if (throwable instanceof HttpException &&  ((HttpException)throwable).code() == 401) {
                       RegistryLoginResult loginResult = holder.login().blockingSingle();
                       return holder.getApi(GuideProfileApi.class)
                          .getProfile(String.valueOf(loginResult.getUserId()), loginResult.getSessionToken());
                     }
                     return Observable.error(throwable);
              }
          }) 
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Consumer<ProfileResult>() {
          @Override
          public void accept(ProfileResult profileResult) throws Exception {
            Log.d("Result", profileResult.toString());
          }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
              Log.e("Result", throwable.getLocalizedMessage());
            }
      });
      

      【讨论】:

      • 如何排除return holder.getApi(GuideProfileApi.class) .getProfile(String.valueOf(loginResult.getUserId()), loginResult.getSessionToken());并更改原始可观察对象的参数?
      • 我相信 rxjava 中的 Observable 是不可变的。一旦你创建了一个 observable,你就不能返回去改变它。
      • 感谢您的咨询。
      • 但是如果第二个 observable 遇到错误,你想重试怎么办?看起来 paul 提供的 defer 解决方案要干净得多。
      猜你喜欢
      • 2021-01-04
      • 1970-01-01
      • 1970-01-01
      • 2016-10-03
      • 2016-03-04
      • 2022-10-06
      • 1970-01-01
      • 2021-09-02
      • 2021-09-15
      相关资源
      最近更新 更多