Observable
(此篇文章翻译自ReactiveX的官方文档)
在ReactiveX中,Observer(观察者)订阅了一个Observable(观察对象)。那么这个观察者会对观察对象发生的任何单一的变化,或者是一连串的变化做出反应,也就是收到观察对象的反馈。这种模式使并发编程变得很容易,因为当我们等待Observable发射变化的时候,我们不需要去阻塞这个操作,也就是没有阻塞这个过程。取而代之的是,我们创造了一个哨兵一样的东西,以观察者的形式,随时准备在Observable变化的时候做出合适的反应。
这一页解释了什么是响应模式,并且什么是Observer(观察者)和 Observable(观察对象)和他们之间是如何订阅的。其他页面展示了你怎么使用各种各样的Observable操作符来将Observable们联系到一起,并且改变他们的行为。
这份文档很多地方都会使用“marble diagrams”(像大理石纹路一样的图解)来解释说明。下边是marble diagrams如何代表Observable和Observables的变化:
tips:
- 第一行是Observable(被观察者)时间线,时间从左流向右。
- 五角星三角形那些是Observable发射出去的变化条目。
- 第一行最右边那条竖线代表Observable成功完成发射
- 这些虚线还有这个长方形的盒子代表Obserbable正在进行一些转变,上边的文字代表转变的性质是什么
- 下边那条线是转变后的Observable的结果
- 如果由于一些原因Observabel转变的过程被非正常错误终止,那么一个“X”会替代竖线的位置。
Background
在许多情况下,你或多或少希望你的指令按照你编写的顺序,逐步逐个执行并完成。但是在ReactiveX中,许多指令可以并行执行,并且他们的结果随后由Observers按任意顺序捕获。不同于使用一个方法,而是以"Observable"的模式定义一种机制,用于检索和转换数据,然后为其订阅观察者,这时在准备就绪的时候,这种机制与订阅者的观察器一起激活,来捕获和相 Observable发射的变化。
这种方法的优点时,当你有一连串互不相干的任务,你可以同时开始他们,而不是等待一个完成后再进行下一个。这样,你整个任务簇执行完毕的时间和你最长的任务所需的时间相同。
这种异步编程与设计的模式有很多称呼,本篇文档会使用如下描述:An observer subscribes to an Observable. 被观察者发射一些消息来通知他的观察者,使用调用观察者方法的模式。
在其他文档和内容中,我们所说的“observer” 有时被称为“subscriber,” “watcher,” or “reactor.” 这种模式一般而言经常被归结为 “reactor pattern”.(观察者模式)。
Establishing Observers
此页面使用类似Groovy的伪代码作为示例,但是在许多语言中都有ReactiveX实现。
在普通的方法调用中 - 也就是说,不是ReactiveX中典型的异步并行调用 - 流程是这样的:
调用方法。
将该方法的返回值存储在变量中。
使用该变量及其新值来做一些有用的事情。
在异步模型中,流程更像是:
定义一个方法,该方法对异步调用的返回值执行一些有用的操作; 这种方法是观察者的一部分。
将异步调用本身定义为Observable。
通过订阅将观察者附加到该Observable(这也启动了Observable的操作)。
继续你的业务; 每当调用返回时,观察者的方法将开始对其返回值或值进行操作 - Observable发出的项。
onNext,onCompleted和onError
Subscribe方法是将观察者连接到Observable的方法。您的观察者实现以下方法的某些子集:
onNext
只要Observable发出一个项目,Observable就会调用此方法。此方法将Observable发出的项作为参数。
onerror的
Observable调用此方法以指示它未能生成预期数据或遇到其他一些错误。它不会进一步调用onNext或onCompleted。 onError方法将参数指示导致错误的原因。
onCompleted
如果Observable在最后一次调用onNext,如果它没有遇到任何错误,则调用此方法。
根据Observable合约的条款,它可以调用onNext零次或多次,然后可以通过调用onCompleted或onError而不是两者来跟随这些调用,这将是它的最后一次调用。按照惯例,在本文档中,对onNext的调用通常称为项目的“发射”,而对onCompleted或onError的调用则称为“通知”。
Unsubscribing
在一些ReactiveX实现中,有一个专门的观察者接口Subscriber,它实现了一个unsubscribe方法。 您可以调用此方法来指示订阅服务器不再对其当前订阅的任何Observable感兴趣。 然后,那些Observable可以(如果他们没有其他感兴趣的观察者)选择停止生成要发出的新项目。
此取消订阅的结果将通过适用于观察者订阅的Observable的运算符链级联,这将导致链中的每个链接停止发出项目。 然而,这并不能保证立即发生,即使在没有观察者观察这些发射之后,Observable也有可能产生并尝试发射物品一段时间。
Some Notes on Naming Conventions
ReactiveX的每种语言特定实现都有自己的命名怪癖。 虽然实现之间存在许多共性,但没有规范的命名标准。
此外,这些名称中的一些在其他情境中具有不同的含义,或者在特定实现语言的习语中看起来很尴尬。
例如,有onEvent命名模式(例如onNext,onCompleted,onError)。 在某些上下文中,这样的名称将指示通过哪些方法注册事件处理程序。 但是,在ReactiveX中,它们自己命名事件处理程序。
“Hot” and “Cold” Observables
Observable何时开始发出其项目序列? 这取决于Observable。 “热”Observable可以在创建项目后立即开始发出项目,因此任何后来订阅该Observable的观察者都只能在中间某处观察序列。 另一方面,“冷”Observable等待观察者在开始发射物品之前订阅它,因此这样的观察者保证从一开始就看到整个序列。
在ReactiveX的一些实现中,还存在称为“可连接”Observable的东西。 这样的Observable在调用Connect方法之前不会开始发出项目,无论是否有任何观察者都订阅了它。
Composition via Observable Operators
Observable和观察者只是ReactiveX的开始。 它们本身只不过是标准观察者模式的轻微扩展,更适合处理一系列事件而不是单个回调。
真正的力量来自“反应性扩展”(因此“ReactiveX”) - 允许您转换,组合,操作和处理Observable发出的项目序列的运算符。
这些Rx运算符允许您以声明方式组合异步序列,同时具有回调的所有效率优势,但没有嵌套通常与异步系统相关联的回调处理程序的缺点。
本文档将有关各种运算符的信息及其用法示例分组到以下页面中:
Chaining Operators
大多数运算符都在Observable上运行并返回一个Observable。 这允许您在链中一个接一个地应用这些运算符。 链中的每个运算符都会修改由前一个运算符的运算产生的Observable。
还有其他模式,如Builder模式,其中特定类的各种方法通过方法的操作修改该对象,对同一类的项进行操作。 这些模式还允许您以类似的方式链接方法。 但是在Builder模式中,方法在链中出现的顺序通常并不重要,Observable运算符的顺序很重要。
一组Observable运算符不能在原始的Observable上独立运行,它发起链,但它们依次运行,每个运算符都由运算符在链中的前一个运算符生成。