第二篇 ReactiveX之Observable

1,828 阅读8分钟

前言

上一篇介绍了什么是ReactiveX,本篇主要介绍Observable。笔者认为把这些概念梳理清楚了,对于后面的应用会比较好上手,不至于一直处于懵懵的开发状态。

Observable

在ReactiveX中,观察者订阅Observable。然后观察者对Observable发出的任何项目或项目序列做出反应。这种模式有助于兵法操作,因为它不需要阻塞等待Observable发射对象。而是以观察者的形式创建一个哨兵,不管在未来任何时候,这个哨兵随时准备着适当的操作来响应Observable。

这个页面解释了什么是响应模式,什么是Observables和Observers(以及Observers是如何订阅Observables的)。其他页面显示了如何使用各种Observable操作符将Observable链接在一起并更改它们的行为。

本文档伴随着“大理石图”进行解释。以下是大理石图如何表示Observable和Observable的转换:

legend.png

背景

在许多软件编程任务中,您或多或少地期望您编写的指令将按照您编写的顺序以递增的方式执行和完成,一次一个。ReactiveX中,许多指令可能会并行执行,它们的结果随后会被“观察者”以任意顺序捕获。与其调用方法,不如以“可观察”的形式定义一种检索和转换数据的机制,然后观察者订阅,在这一点上,先前定义的机制启动,观察者站岗,随时捕捉并响应其排放物。
这种方法的一个优点是,当你有一堆彼此不依赖的任务时,你可以同时开始所有任务,而不是等待每一个任务完成后再开始下一个任务——这样,你的整个任务包只需要和任务包中最长的任务一样长的时间就可以完成。
有许多术语用来描述这种异步编程和设计的模型。本文档将使用以下术语:观察员订阅Observable。Observable通过调用观察者的方法来向其观察者发出项目或发送通知。
在其他文档和其他上下文中,我们称之为“观察者”的东西有时被称为“订阅者”、“观察器”或“反应器”。这种模型通常被称为”反应器模式“。

建立观察者

本页使用类似Groovy的伪代码作为示例,但有许多语言的ReactiveX实现。

在一个普通的方法调用中——也就是说,不是ReactiveX中典型的异步、并行调用——流是这样的:

  1. 调用一个方法。
  2. 将该方法的返回值存储在变量中。
  3. 使用该变量及其新值来做一些有用的事情。 或者,类似这样的事情:
// make the call, assign its return value to `returnVal`
returnVal = someMethod(itsParameters);
// do something useful with returnVal

在异步模型中,流程更像这样:

  1. 定义一个方法,用异步调用的返回值做一些有用的事情;这种方法是观测者的一部分。

  2. 将异步调用本身定义为Observable。

  3. 通过订阅Observable将观察者连接到该Observable(这也会启动Observable的操作)。

  4. 继续你的事业;每当调用返回时,观察者的方法将开始对其返回值进行操作,即Observable发出的项。

它看起来像这样:

// defines, but does not invoke, the Subscriber's onNext handler
// (in this example, the observer is very simple and has only an onNext handler)
def myOnNext = { it -> do something useful with it };
// defines, but does not invoke, the Observable
def myObservable = someObservable(itsParameters);
// subscribes the Subscriber to the Observable, and invokes the Observable
myObservable.subscribe(myOnNext);
// go on about my business

onNext, onCompleted, and onError

Subscribe是将观察者连接到Observable的方法。您的观察者实现了以下方法的一些子集:
onNext
每当Observable发出项目时,Observable都会调用此方法。此方法将Observable发出的项作为参数。
onError
Observable调用此方法以指示它未能生成预期的数据或遇到了其他错误。它不会再调用onNext或onCompleted。onError方法将导致错误的原因作为其参数。
onCompleted
Observable在最后一次调用onNext之后调用这个方法,如果它没有遇到任何错误的话。

根据Observable合约的条款,它可以调用onNext零次或多次,然后可以在这些调用之后调用onCompleted或onError,但不能同时调用两者,这将是它的最后一次调用。按照惯例,在本文档中,对onNext的调用通常被称为项目的“排放”,而对onCompleted或onError的调用被称为“通知”。
一个更完整的订阅调用示例如下所示:

def myOnNext     = { item -> /* do something useful with item */ };
def myError      = { throwable -> /* react sensibly to a failed call */ };
def myComplete   = { /* clean up after the final response */ };
def myObservable = someMethod(itsParameters);
myObservable.subscribe(myOnNext, myError, myComplete);
// go on about my business

取消订阅

在一些ReactiveX实现中,有一个专门的观察者接口Subscriber,它实现了一个取消订阅方法。您可以调用此方法来指示订阅服务器不再对其当前订阅的任何Observable感兴趣。然后,这些Observable可以(如果它们没有其他感兴趣的观察者)选择停止生成要发出的新项目。

取消订阅的结果将通过应用于观测者订阅的Observable的运算符链级联回来,这将导致链中的每个链接停止发射项目。然而,这并不能保证立即发生,即使在没有观察员留下来观察这些排放物之后,Observable也有可能在一段时间内产生并试图排放这些物品。

关于命名约定的几点注记

ReactiveX的每种特定于语言的实现都有自己的命名怪癖。虽然实现之间有许多共性,但没有规范的命名标准。

此外,其中一些名称在其他上下文中有不同的含义,或者在特定实现语言的习语中显得很尴尬。

例如,有onEvent命名模式(例如onNext、onCompleted、onError)。在某些上下文中,这样的名称将指示用于注册事件处理程序的方法。然而,在ReactiveX中,它们自己命名事件处理程序。

“热”和“冷”Observables

“热”和“冷”Observable何时开始发射其项目序列?这取决于Observable。“热门”Observable可能会在创建后立即开始发射项目,因此任何后来订阅该Observable的观察者都可能会在在中间的某个位置开始观察序列。另一方面,一个“冷”的Observable在开始发射项目之前要等待,直到观察者订阅它,因此这样的观察者可以保证从一开始就看到整个序列。

在ReactiveX的一些实现中,还有一种称为“可连接”的Observable。这样的Observable在调用其Connect方法之前不会开始发出项,无论是否有任何观察者订阅了它。

通过Observable操作符进行组合

Observables和observers只是ReactiveX的开始。就其本身而言,它们只不过是标准观察器模式的一个轻微扩展,更适合处理一系列事件,而不是单个回调。

真正的力量来自“响应式扩展”(因此是“ReactiveX”),这些操作符允许您转换、组合、操纵和处理Observables发射的项目序列。

这些Rx运算符允许您以声明的方式将异步序列组合在一起,具有回调的所有效率优势,没有通常与异步系统相关联的嵌套回调处理程序的缺点。

本文档将有关各种运算符及其用法示例的信息分组到以下页面中:

这些页面包括一些运算符的信息,这些运算符不是ReactiveX核心的一部分,但在一个或多个特定于语言的实现和/或可选模块中实现。

链式运算符(操作符)

大多数运算符对Observable进行操作并返回Observable。这允许您在链中一个接一个地应用这些运算符。链中的每个操作符都会修改上一个操作符的操作所产生的Observable。

还有其他模式,如Builder模式,其中特定类的各种方法通过对该方法的操作来修改该对象,从而对同一类的项进行操作。这些模式还允许您以类似的方式链接方法。但是,在Builder模式中,方法在链中出现的顺序通常并不重要,而Observable运算符的顺序很重要。

Observable运算符链并不独立于发起该链的原始Observable进行操作,但它们依次进行操作,每个运算符都对链中前一个运算符生成的Observable执行操作。

总结

读完本篇,相信小伙伴们应该对Observable和observers的概念比较清楚了,一个是可以被观察事物,一个是对该事物进行了订阅(即观察),订阅的时候需要提供一些响应的方法。

有关于Operators的东西,我们在rxwift的使用中再介绍,因为内容太多了,在reactiveX里面没法介绍。