RxSwift 中的 Observable 详解 (翻译一)

相关文章链接:

  1. RxSwift 中的 Subject
  2. RxSwift 上手详解 —— 入门篇

ReactiveX中一个观察者(observer)订阅一个被观察的对象(Observable)。那个观察者对Observable发出的无论是单个对象或者是一串对象作出反馈。这种模式有利于并发操作因为它不需要阻塞线程,当等待Observable发送对象的过程中,它建立一种xiang哨兵一样的机制,我们称之为观察者,它会一直关注那个Observable然后做出适当的反应。

这篇文章解释了reactive pattern是什么,Observable(被观察的对象)和observer(观察者)是什么,以及observer如何订阅Observable。其他的几篇文章会解释如何使用Observable的各种操作符去链接不同的Observables并且改变他们的行为。

这篇文章会结合一些“弹子图”进行解释。这张图简单介绍了弹子图如何代表Observables和Observables的变形。第一行的一个个图形代表Observable发送的一个个事件,每个事件都经过翻转的操作,得到新的Observable事件,按照顺序发送。


背景介绍

在很多软件编程任务中,你或多或少希望你写的指令会逐步地执行和完成,一次一条,按照你写的顺序。但在ReactiveX中,很多指令同时执行,执行结果会在稍后以任意的顺序被observer捕捉。与以往调用函数不同,你以Observable的形式定义一种新的得到数据并转化数据的机制,并且可以创建一个observer订阅它,当这种机制被触发,observer就会捕捉到并且做出反应。

这种方式的优点在于当你有一些互不关联的任务时,你可以同时启动它们而不是等这些任务一个个完成才开始另外一个,这样的话,完成所有任务的总时长只是完成那个最长任务的时长。

有很多用来描述这种异步编程和设计的术语,这里我们用以下的术语:一个观察者订阅一个被观察对象(An observer subscribes to an Observable)。一个被观察对象(Observable)通过调用观察者(observer)的方法来给观察者(observer)发送条目或者通知

在其他文章中,可能会把observer称之为订阅者(subscriber),观察者(watcher)或者反映者(reactor)。这个模式经常被引用为“反应器模式”

创建观察者

这篇文章中将会用一些伪代码来展示一些例子,ReactiveX的实现可以用很多种语言.

在一个普通的方法调用中,流程是这样的:
1. 调用函数
2. 把函数的返回值存在一个变量里
3. 用这个变量和新的值去做一些有用的事

// make the call, assign its return value to `returnVal`
returnVal = someMethod(itsParameters);
// do something useful with returnVal

在异步模型里,流程应该是这样的:
1. 定义一个方法,这个方法可以使用异步调用的返回值做一些有用的事,这个方法是observer的一部分
2. 定义一个异步调用,称它为Observable
3. 通过订阅的方式,把这个observer附加到Observable上去(这也同时初始化了Observable的行为actions)
4. 无论那个异步调用返回什么,observer的方法都会开始对异步调用的返回值进行操作,这些返回值其实也就是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)的方法是指你如何把一个observer与一个Observable联系起来。你的observer会实现下面的其中一些方面。

  • onNext

当Observable发送一个对象的时候,Observable就开始调用 onNext方法,这个方法把Observable发送的对象作为参数

  • onError

当Observable不能产生希望的数据或者遇到一些错误的时候,就会调用这个onError方法。调用这个方法之后,将不会再调用onNext或者onCompleted这些函数。onError方法把error作为参数。

  • onCompleted

如果没有遇到任何错误,Observable在最后一次调用onNext之后调用这个方法。

根据Observable规定(Observable Contract),Observable调用onNext大于等于零次,然后会接着调用onCompleted或者onError方法,但不会两个都调用,一旦调用这两个方法中的任何一个,这个方法将会是最后一次调用。我们约定俗成地把onNext的调用称为事项的发送(emissions of items),而把onCompleted或者onError叫做通知(notifications).

一个更加完整的subscribe调用例子大概是这样的:

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的实现中,有一个专门的observer接口,订阅器(Subscriber),它实现了取消订阅这个方法。如果Subscriber再也不对现在订阅的Observable感兴趣了,你可以调用这个方法去取消订阅。那些Observable将不再会发送新的事件(如果Observable没有其他observer的话)。

取消订阅的操作会顺着运用在Observable上的操作符一级一级地向前推,让这个操作符链上的每个节点都停止发送事件。这一过程可能需要一定的事件,并不保证会立刻发生,对一个Observable来说很有可能在没有observer订阅它的情况下仍然会发一段时间的事件。

一些关于命名规范的提示

ReactiveX中的不同语言每一种都有它们自己的命名规范。尽管有一点共同点,但是没有一个各种语言通用的标准。

更重要的是这些名称在其他的上下文中可能有会推断出来不同的意义,或者在某一种特别的语言环境下看起来特别奇怪。

举个例子来说,onEvent命名模式中(例如onNext,onCompleted,onError),在一些语言的上下文中,这些名称会显示注册了哪些事件处理器(event handler),而在ReactiveX中,这些名称就是event handler本身。

Hot Observable 和 Cold Observable

什么时候一个Observable会开始发送一串事件呢?取决于这个Observable。一个“hot” Observable一旦被创建就会发送事件,所以任何之后订阅这个Observable的observer会从中间的某个点开始观察。一个“cold” Observable直到有一个observer订阅它,它才开始发送事件,所以observer保证能够观察到整个事件串。

在一些ReactiveX的实现中,有一个被称为可连接的(Connectable)Observable的东西,这个Observable直到调用Connect方法才会开始发送事件,无论有没有observer订阅它。

运用Observable操作符进行组合

Observable和observer仅仅是ReactiveX的开始,它们本身仅仅是一种标准observer模式的拓展延伸而已,能更好地处理事件串。

真正强大的功能来自于“reactive extensions”(这也是为什么ReactiveX的名字由来),reactive extensions指的是操作符,这些操作符可以让你变化,组合,处理那些Observable发出来的一串串事件。

这些操作符让你能够把异步序列组合在一起,以一种描述性的方式组合在一起,同时运用了回调函数(callbacks)的高效性,摒弃了异步系统中常常出现的冗长的callback嵌套问题。

ReactiveX官网有各种操作符的介绍和用法

链式操作符

大多数操作符处理一个Observable并且返回一个Observable。这个特点能够让你一个接一个地运用这些操作符,像一个链条一样。每一个在链条中的操作符都处理从上一个操作符传下来的Observable然后传给下一个操作符。

也有一些其他的模式,像Builder Pattern,在这种模式中,用一个类的各种不同的方法对这个类的事件进行操作,通过这些方法的操作改变那些对象。这些模式也可以用链式的方式,但在Builder Pattern里,与Observable操作符不同的是,方法在链中的顺序并不重要。

Observable操作符不是对最初的那个Observable进行操作,而是根据链条中上一个操作符产生的Observable进行操作。

原文链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容