retryWhen()停止重试后如何获得Throwable?

时间:2018-03-05 13:45:14

标签: rx-java2

  private String stringResult=null;
  private Throwable throwableResult=null;

  @Test
  public void whereIsTheThrowable() {
    Observable.just("foo")
      .map(this::justBlowUp)
      .retryWhen(errors -> errors.zipWith(Observable.range(1, 3), (n, i) -> i))
      .subscribe(s -> stringResult=s, throwable -> throwableResult=throwable);

    assertNull(stringResult);
    assertNotNull(throwableResult);
  }

  private String justBlowUp(String s) {
    throw new RuntimeException();
  }

该测试因RxJava 2.1.7而失败。 retryWhen()似乎消耗了Throwable,即使它不再重试。 subscribe() lambda没有获得任何Throwable。虽然这个测试很愚蠢(justBlowUp()只是爆炸),你可以想象一个Observable链,其中工作通常成功,偶尔会失败,很少连续失败四次。但是,在这种情况下,将Throwable用于记录目的会很有用。

retryUntil()允许subscribe()获得最终Throwable ...但是在retryUntil()我们根本没有Throwable而无法制作决定它(例如,如果它似乎是一个互联网连接错误,重试N次,但其他一切都快速失败)。 retryWhen()似乎是更强大的选项,但在Throwable停止重试后,我们如何获得最终retryWhen()

我可以使用一个字段来保存Throwable,设置在retryWhen()逻辑中,但感觉应该有一个更惯用的解决方案。

1 个答案:

答案 0 :(得分:5)

retryWhen将处理程序的完成视为正常完成的指示符,因此,处理程序在重试选项用尽后应该失败:

Observable.just("foo")
.map(this::justBlowUp)
.retryWhen(errors -> errors.flatMap(new Function<Throwable, Observable<Integer>>() {
    int count;
    @Override
    public Observable<Integer> apply(Throwable error) {
        if (count++ < 3) {
            return Observable.just(count);
        }
        return Observable.error(error);
    }
}))
.test()
.assertFailure(RuntimeException.class);