Observable的doOnError正确位置

时间:2015-04-27 13:29:23

标签: java rx-java

我对Observers有些新意,我仍在努力解决这些问题。我有以下代码:

observableKafka.getRealTimeEvents()
        .filter(this::isTrackedAccount)
        .filter(e -> LedgerMapper.isDepositOrClosedTrade((Transaction) e.getPayload()))
        .map(ledgerMapper::mapLedgerTransaction)
        .map(offerCache::addTransaction)
        .filter(offer -> offer != null)  // Offer may have been removed from cache since last check
        .filter(Offer::isReady)
        .doOnError(throwable -> { 
              LOG.info("Exception thrown on realtime events");
          })
        .forEach(awardChecker::awardFailOrIgnore);

getRealTimeEvents()会返回Observable<Event>

.doOnError的位置是否重要?另外,在这段代码中添加多个调用会产生什么影响?我已经意识到我可以做到并且所有这些都被调用了,但我不确定它的用途是什么。

2 个答案:

答案 0 :(得分:22)

是的,确实如此。 doOnError在错误在特定点传递流时起作用,因此如果doOnError之前的操作符抛出,则会调用您的操作。但是,如果您进一步放置doOnError,可能会也可能不会调用它,具体取决于链中的下游运算符。

鉴于

Observer<Object> ignore = new Observer<Object>() {
    @Override public void onCompleted() {
    }
    @Override public void onError(Throwable e) {
    }
    @Override public void onNext(Object t) {
    }
};

例如,以下代码将始终调用doOnError:

Observable.<Object>error(new Exception()).doOnError(e -> log(e)).subscribe(ignore);

但是,此代码不会:

Observable.just(1).doOnError(e -> log(e))
.flatMap(v -> Observable.<Integer>error(new Exception())).subscribe(ignore);

大多数运营商都会退回源自下游的异常。

如果您通过doOnErroronErrorResumeNext转换例外,则可以添加多字段onExceptionResumeNext

Observable.<Object>error(new RuntimeException())
.doOnError(e -> log(e))
.onErrorResumeNext(Observable.<Object>error(new IllegalStateException()))
.doOnError(e -> log(e)).subscribe(ignore);

否则,您将在链的多个位置记录相同的异常。

答案 1 :(得分:4)

doOn???方法存在副作用,处理并不是您的核心商业价值。记录是一个非常好的用途。 也就是说,有时你想做一些更有意义的错误,比如重试,或者向用户显示消息等......对于这些情况,&#34; rx&#34;方法是在subscribe电话中处理错误。

doOnError(以及其他doOn方法)将原始Observable包装成新的onError并向其添加行为(显然是围绕其Subscriber方法)。这就是为什么你可以多次打电话的原因。能够在链中的任何地方调用它的一个好处是,您可以访问否则将从流的使用者(Venue.find({ is_published: true, restaurant_services: { contains: '"delivery":"1"', contains: '"takeout":"1"' }, restaurant_specialties: { contains: '"breakfast":"1"', } }).exec )隐藏的错误,例如因为在那里重试了链......