【问题标题】:RxJava: UndeliverableException when flatMap combined with switchMapRxJava:flatMap 与 switchMap 结合时出现 UndeliverableException
【发布时间】:2022-08-03 17:24:38
【问题描述】:

TL;博士

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

结构

我正在制作一些复杂的流——结合flatMapswitchMap——如下所示,在 RxKotlin (RxJava 3) 中:

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 最终有可能返回错误。

例外

事实证明,有时来自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,并且只保留最新的一个)

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

    标签: rx-kotlin rx-java3


    【解决方案1】:

    RxJava2 Official Doc 解释了一些关于 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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-17
      • 2015-12-03
      • 1970-01-01
      • 2019-06-02
      • 2010-11-18
      • 1970-01-01
      相关资源
      最近更新 更多