咱们已经看到了如何处理观察者中的错误,然而,到那时,咱们实际上已经超出了 Monad 的范围。错误可能有不少种,并非每个错误都值得一路推到顶端。在标准Java中,您能够在任何级别捕获异常,并决定是在那里处理仍是进一步抛出。相似地,在Rx中,您能够基于错误定义行为,而没必要终止可观察到的行为,并强制观察者处理全部的问题。ios
在下一个示例中,咱们将把错误转换为要打印的正常值:git
输出:github
onErrorResumeNext 容许您用另外一个序列恢复失败的序列。该错误不会出如今所获得的可观察到的结果中。数据库
第一个重载在每种状况下都使用相同的可观察到的后续操做。第二个重载容许您根据发生的错误决定顺序。缓存
输出:函数
没有什么能中止 resumeSequence 的失败。事实上,若是您想更改错误的类型,您能够当即返回一个可观察到的错误。在标准Java中,组件可能会决定它们不能处理错误,而应该从新抛出错误。在这种状况下,一般会在原始错误周围包装一个新的异常,从而提供额外的上下文。在Rx中也能够这样作。spa
如今序列仍然失败,可是您已经将原来的错误封装在一个新的错误中。code
onExceptionResumeNext与onErrorResumeNext只有一个区别:它只捕获做为异常的错误资源
输出:字符串
若是错误是不肯定的,那么重试多是有意义的。重试从新订阅源并再次从星号发出全部信息。
若是错误没有消失,retry()将把咱们锁定在无限重试的循环中。第二个重载限制重试的次数。若是错误持续存在且序列失败n次,则重试(N)也将失败。让咱们看一个例子:
这边有个输出是 rx.exceptions.OnErrorNotImplementedException,理解不了 ???
在这里,咱们已经指定要重试一次。咱们的可观测值在两个值后失败,而后再试一次,再失败一次。第二次失败时,容许异常经过。
在这个例子中,咱们作了一些棘手的事情:咱们将订阅状态设置为有状态,以证实可观察到的是从源从新启动的:它第二次产生了不一样的值。retry不缓存任何元素,好比重播,这样作也没有意义。只有在有反作用或可观察到的是热的状况下,重试才有意义。
一旦发生故障,retry 将从新启动订阅。若是咱们须要更多的控制,咱们可使用retryWhen
retryWhen的参数是一个接受可观察值并返回另外一个值的函数。可观察到的输入会发出当遇到时再次出现的全部错误。当重试时可观察到的信号:
若是它以错误终止,不重试
若是成功终止,则重试也成功终止。
请注意,可观察到的信号类型和发出的实际值并不重要。这些值被丢弃,可观测值仅用于计时。
在下一个示例中,咱们将构造一个重试策略,在重试以前等待100 ms。
输出:
咱们的源可观察到发出2个值,并当即失败。当发生这种状况时,内部可观察到的故障将在发出错误时重试。咱们延迟发射100毫秒,并将其发送回信号重试。 take(2)
保证咱们的信号可观测到的将终止后,咱们收到两个错误。
using 操做符用于从须要管理的资源中建立observables。它保证不管什么时候以何种方式终止订阅,都将管理您的资源。若是只使用create,就必须在传统Java范例中进行管理,并将其注入Rx中。在Rx中,using 是一种更天然的管理资源的方式。
当新的订阅开始时,ResourceFactory 将租用必要的资源。当再也不须要资源时,将使用disposeAction对其进行处置。不管订阅以何种方式终止(成功或失败),都将执行Disposal操做。
在下一个示例中,咱们假设字符串是须要管理的资源。
输出:
当咱们订阅值时,将调用资源工厂函数,该函数返回“MyResource”。该字符串用于生成一个可观察的字符串,它会发出字符串中的全部字符。一旦订阅结束,资源将被释放。字符串不须要比垃圾回收器所作的更多的管理工做。资源实际上可能须要这样的管理,例如数据库链接、打开的文件等
这里须要注意的是,咱们负责终止可观察到的内容,就像咱们在使用Create方法时所作的那样。使用create,终止是一个语义问题。using,而不是终止,首先就会破坏使用它的意义。只有在终止时才会释放资源。若是咱们没有调用o.onCompleted(),那么序列将被假定仍然是活动的,而且须要它的资源
原文连接:
https://github.com/Froussios/Intro-To-RxJava/blob/master/Part%203%20-%20Taming%20the%20sequence/3.%20Advanced%20error%20handling.md