RxJava:flatMap与switchMap组合时出现UndeliverableException



TL;DR

我认为flatMapswitchMap组合可能无法正确终止流,因此会发生UndeliverableException。我该怎么解决这个问题?

结构

我正在RxKotlin(RxJava 3(中制作一个有点复杂的流——与flatMapswitchMap相结合——如下所示:

someObservable
.flatMapMaybe {
if (matchCondition(it)) Maybe.just(it)
else Maybe.never()
}.flatMapSingle {
procedureMiddle(it) // Inconsistent-time-consuming Single
}.switchMap {
procedureLater(it)
}.doOnError {
dealWithError(e)
}.retry()
.subscribeBy(
// ...
)

flatMapSingle中的procedureMiddle最终有机会返回Error。

例外情况

结果表明,有时procedureMiddle的错误可能会跳出结构,retry不会忽略,doOnError:中的dealWithError也不会处理

W/System.err: io.reactivex.rxjava3.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | my.custom.app.CustomException
// traces indicates that the Exception is thrown from inside procedureMiddle

问题

事实上,UndeliverableException并没有真正导致崩溃,但它对我来说有点烦人——尤其是它看起来像是我需要处理的情况。然而,我认为结构写得正确吗?所以我的问题是:

  1. switchMap真的(正确地(终止了flatMap的最后一个流吗?(可用于预防UndeliverableException?(
  2. 如果是,我应该在代码的哪一部分进行调整?如果不是这样的话,我该如何防止我的结构出现异常?(我想在procedureMiddle之后加入procedureLater,只保留最新的(

任何建议或解释都会有所帮助。

RxJava2官方文档解释了一些关于UndeliverableException:的内容

UndeliverableException:包装由于Subscriber/Observer的生命周期限制而无法交付的原始异常。

所以,实际上,这并不意味着你的代码(直接(有任何问题。它只是提醒您,某些流在您结束/取消/处理它们之后仍然会抛出错误。

关于问题:

switchMap真的(正确地(终止了flatMap的最后一个流吗?(可用于防止UndeliverableException?(

  • 是的,它终止了最后一个流
  • UndeliverableException号仍然会发生。因为它终止了最后一个流,所以如果最后一个数据流抛出错误,则该错误将被包装并作为UndeliverableException抛出

如果是,我应该调整代码的哪一部分?如果不是这样的话,我该如何防止我的结构出现异常?

您不需要调整代码,也不需要阻止UndeliverableException,因为它总是有机会在处理/取消/结束任何流时出现(手动甚至自动(

我建议忽略它:

RxJavaPlugins.setErrorHandler {
if (it is UndeliverableException) {
// This happens when throwable comes out AFTER subscription is canceled or disposed.
// Not what we care about as it is likely disposed by user or system.
Log.d(
"Application", "UndeliverableException: ignored.n" +
"$it: problem ${it.cause} / ${it.cause?.message}n" +
"at ${it.cause?.stackTraceToString()}"
)
return@setErrorHandler
}
// other Exceptions: do some report
}

相关内容

  • 没有找到相关文章

最新更新