我对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
的位置是否重要?另外,在这段代码中添加多个调用会产生什么影响?我已经意识到我可以做到并且所有这些都被调用了,但我不确定它的用途是什么。
答案 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);
大多数运营商都会退回源自下游的异常。
如果您通过doOnError
或onErrorResumeNext
转换例外,则可以添加多字段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
)隐藏的错误,例如因为在那里重试了链......