UniRx学习之路(一)——响应式编程模式(Reactive Pattern)

一、Rx模式

1.使用观察者模式

  • 创建:Rx可以方便的创建事件流和数据流
  • 组合:Rx使用查询式的操作符组合和变换数据流
  • 监听:Rx可以订阅任何可观察的数据流并执行操作

2.简化代码

  • 函数式风格:对可观察数据流使用无副作用的输入输出函数,避免了程序里错综复杂的状态
  • 简化代码:Rx的操作符通常可以将复杂的难题简化为很少的几行代码
  • 异步错误处理:传统的try/catch没办法处理异步计算,Rx提供了合适的错误处理机制
  • 轻松使用并发:Rx的Observable和Schedulers让开发者可以摆脱底层的线程同步和各种并发问题

3.使用Observable的优势

Rx扩展了观察者模式用于支持数据和事件序列,添加了一些操作符,它让你可以声明式的组合这些序列,而无需关注底层的实现,如线程、同步、线程安全、并发数据结构和非阻塞IO。

二、Rx背景知识

在很多软件编程任务中,或多或少你都会希望你写的代码能按照编写的顺序,一次一个的顺序执行。但是在ReactiveX中,很多指令可能是并行执行的,之后他们的执行结果才会被观察者捕获,顺序是不确定的。为了达到这个目的,需要定义一种获取和变换数据的机制而不是调用一个方法。在这种机制下,存在一个可观察对象(Observable),观察者(Observer)订阅(subscribe)它,当数据就绪时,之前定义的机制就会分发数据给一直处于等待状态的观察者哨兵。

这种方法的优点是,如果你有大量的任务要处理,而且他们之间没有依赖关系,你可以同时开始执行它们,而不用等待一个完成再开始下一个(顺序执行)。通过调用观察者的方法,Observable发射数据或通知给它的观察者。

在其他地方,有时也将Observer称作Subscriber、Watcher、Reactor。这个模型通常被称为Reactor模式。

三、Observables

异步模型中的方法调用流程:

1.定义一个方法,它完成某些任务,然后从异步调用中返回一个值,这个方法是观察者的一部分

2.强这个异步调用本身定义为一个Observable

3.观察者通过订阅(Subscribe)操作关联到那个Observable

4.继续你的业务逻辑,等方法返回时,Observable会发射结果,观察者的方法会开始处理结果或结果集

回调方法(onNext,onCompleted,onError)

Subscribe方法用于将观察者连接到Observable,你的观察者需要实现以下方法的一个子集:

  • onNext(T item)

  Observable调用这个方法发射数据,方法的参数就是Observable发射的数据,这个方法可能会被调用多次

  • onError(Exception ex)

  当Observable遇到错误或无法返回期望的数据时会调用这个方法,这个调用将会终止Observable,后续不会再调用onNext和onCompleted,onError方法的参数是抛出的异常

  • onCompleted()

  正常终止,如果没有遇到错误,Observable在最后一次调用onNext之后调用此方法

 根据Observable协议的定义,onNext可能会被调用零次或者多次,最后会有一次onCompleted或onError调用(不同时调用),传递数据给onNext通常被称作发射,onCompleted和onError被称作通知。

Observables的“冷”和“热”

Observable什么时候开始发射数据序列?这取决于Observable的实现,一个“热”的Observable可能一创建完就开始发射数据,因此所有后续订阅它的观察者可能从序列中间的某个位置开始接受数据(有一些数据错过了)。一个“冷”的Observable会一直等待,直到有观察者订阅它后才开始发射数据,因此这个观察者可以确保会受到整个数据序列。

 四、Subject

 Subject可以看成是一个桥梁或者代理,在某些ReactiveX实现中,它同时充当了Observer和Observable的角色。因为它是一个Observer,可以订阅一个或多个Observable;又因为它是一个Observable,可以转发它收到(Observer)的数据,也可以发射新的数据。

由于一个 Subject订阅一个Observable,它可以触发这个Observable开始发射数据(如果那个Observable是“冷”的——就是说,它等待有订阅才开始发射数据)。因此有这样的效果,Subject可以把原来那个“冷”的Observable编程“热”的。

AsyncSbuject

一个AsyncSbuject只在原始Observable完成后,发射来自原始Observable的最后一个值(如果原始Observable没有发射任何值,AsyncSbuject也不发射任何值)。它会把这最后一个值发射给任何后续的观察者。

然而,如果原始Observable因为发生了错误而终止,AsyncSbuject将不会发射任何数据,只是简单的向前传递这个错误通知。

BehaviorSubject

当观察者订阅BehaviorSubject时,它开始发射原始Observable最近发射的数据(如果此时还没有收到任何数据,它会发射一个默认值),然后继续发射其他任何来自原始Observable的数据。

然而,如果原始的Observable因为发生了一个错误而终止,BehaviorSubject将不会发射任何数据,只是简单的向前传递这个错误通知。

PublishSubject

PublishSubject(在某些地方称为Subject)指挥把在订阅发生的时间点之后来自Observable的数据发射给观察者。需要注意的是,PublishSubject可能会一创建完成就立刻开始发射数据(除非你可以阻止它发生),因此这里有一个风险,在Subject被创建后到有观察者订阅它之前这个时间段内,一个或多个数据可能会丢失。如果要确保来自原始Observable的所有数据都被分发,你需要这样做:或者使用Create创建那个Observable以便手动给它引入“冷”Observable行为(当所有观察者都已经订阅时才开始发射数据),或者改用ReplaySubject。

然而,如果原始的Observable因为发生了一个错误而终止,PublishSubject将不会发射任何数据,只是简单的向前传递这个错误通知。

ReplaySubject

ReplaySubject会发射所有来自原始Observable的数据给观察者,无论它们是何时订阅的。也有其他版本的ReplaySubject,在重放缓存增长到一定大小的时候或过了一段时间后会丢弃旧的数据。

如果你把ReplaySubject当做一个观察者使用,注意不要从多个线程中调用它的onNext发放(包括其他on系列方法),这可能导致同时(非顺序)调用,这会违反Observable协议,给Subject的结果增加了不确定性。

 

posted on 2017-02-03 16:49  Fantasia丶叶子  阅读(1176)  评论(0编辑  收藏  举报

导航