在下面的代码中,我有一个嵌套的Observable。 flatMap中的sendMessage调用sendMessage函数,这也是一个可观察到的函数。如果在此嵌套可观察的对象中发生异常,则假设onExceptionResumeNext可以捕获该异常,处理该异常,然后继续进行,就好像什么都没有发生一样。确实捕获到异常,但是一旦完成对异常的处理,流中将不再产生任何排放。甚至没有调用doOnComplete。本质上,onExceptionResume接下来只是挂起。
我尝试了onErrorReturnItem,但结果相同。我没有在Stackoverflow或其他地方找到一个单独的示例,该示例甚至在嵌套的可观察对象内显示onExceptionResumeNext或onErrorResumeNext或onErrorReturnItem,并且在处理了一天之后,我怀疑可能无法支持嵌套的错误处理程序。
注意:在onExceptionResumeNext中,我目前正返回
Observable.empty<MessageToSend>()
在我的实际代码中,我有处理异常的代码,我尝试返回一个可观察的对象以及仅返回数据。没关系,我总是挂着。
fun postMessages() {
val msgToSendPublisher = BehaviorSubject.createDefault(MessageToSend())
msgToSendPublisher
.flatMap { _ ->
App.context.repository.getMessageToSend().toObservable()
}
.doOnError { error ->
if (error is EmptyResultSetException)
App.context.repository.setSendStatusToNotSendingForAllMessages()
}
.doOnNext { messageToSend ->
App.context.repository.updateMessage(messageToSend)
}
.flatMap { messageToSend ->
App.context.repository.sendMessage(messageToSend)
}
.doOnNext { messageToSend ->
messageToSend.dateSent = Date()
App.context.repository.updateDateLastMessageSent(messageToSend)
}
.doOnNext { messageToSend ->
if (messageToSend.totalMessagesToSend == 1)
App.context.repository.updateSendStatus(messageToSend, MessageSendStates.NOT_SENDING)
else
Observable.just(messageToSend)
}
.doOnNext {
msgToSendPublisher.onNext(it)
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ messageToSend ->
},
{ ex ->
onMessagesSent()
},
{
onMessagesSent()
}
)
}
fun sendMessage(messageToSend: MessageToSend): Observable<MessageToSend> {
val obs = Observable.fromCallable {
if (messageToSend.totalMessagesToSend == 3)
throw Exception("Couldn't send to recipient.")
messageToSend
}.map {
storeMessageSent(messageToSend)
}.onExceptionResumeNext {
Observable.empty<MessageToSend>() // Hangs here.
).doOnComplete {
addNewMessageIfRequired(messageToSend, newMessage)
}
return obs
}
更新:
我决定测试一个发现的示例代码,该示例代码使用onExceptionResumeNext。看起来像这样:
Observable.fromArray(1, 2, 3)
.doOnNext {
if (it == 2) {
throw (RuntimeException("Exception on 2"))
}
}
.onExceptionResumeNext(
Observable.just(10)
)
.subscribe(
{
var x = it
},
{
var x = it
},
{
var x = 0
x++
}
)
如果在onExceptionResumeNext内部的行上放置一个断点,则每当您第一次运行可观察对象时,不仅在引发异常时,都会调用该断点。显然,这是RxJava文档中未发现的行为。任何开发人员都会感到只有在引发异常时才会调用它。在上面的示例中,将值设置为10确实不是问题。它实际上是为异常发生时的情况设置返回值。但是,如果这是更复杂的代码将内容存储在数据库中(我的应用程序执行此操作),则在初始化observable时将调用它-这确实很糟糕。尽管有这个发现,它仍然不能解决我的问题,因为没有其他物品被放出。我在示例代码中发现的是,当调用onExceptionResumeNext时,也调用了onComplete。太糟糕了,文档也没有提到。
答案 0 :(得分:1)
您可能想使用defer
来推迟执行函数调用,这些函数调用会导致副作用:
Observable<Integer> createFallback() {
System.out.println("Why is this executing now?!");
return Observable.empty();
}
Observable.<Integer>error(new Exception())
.onExceptionResumeNext(createFallback())
.subscribe();
createFallback
之所以运行,是因为您通过调用将其指定为运行。如果序列被重写,原因应该更加明显:
Observable<Integer> fallback = createFallback();
Observable.<Integer>error(new Exception())
.onExceptionResumeNext(fallback)
.subscribe();
现在,如果您注释掉可观察错误的部分,它是否仍执行createFallback()
?是的,RxJava甚至还没有参与。
如果您不希望这种副作用不会发生在createFallback
上,则必须推迟执行整个方法,为此可以使用一个运算符:defer
:
Observable.<Integer>error(new Exception())
.onExceptionResumeNext(Observable.defer(() -> createFallback()))
.subscribe();
我认为在Kotlin中看起来像这样:
Observable.error(new Exception())
.onExceptionResumeNext(Observable.defer { createFallback() })
.subscribe()