ReactiveX 探索(一)— Rx 介绍

ReactiveX 官网

ReactiveX 文档中文翻译

RxJava GitHub 主页

RxJava Wiki 主页

一、ReactiveX 介绍

微软给的定义是,Rx 是一个函数库,让开发者可以利用可观察序列和 LINQ 风格查询操作符来编写异步和基于事件的程序,使用 Rx,开发者可以用 Observables 表示异步数据流,用 LINQ 操作符查询异步数据流, 用 Schedulers 参数化异步数据流的并发处理,Rx 可以这样定义:Rx = Observables + LINQ + Schedulers

ReactiveX.io 给的定义是:Rx 是一个使用可观察数据流进行异步编程的编程接口,ReactiveX 结合了观察者模式、迭代器模式和函数式编程的精华。

二、ReactiveX 模式

2.1 使用观察者模式

  • 创建:Rx 可以方便地创建事件流和数据流

  • 组合:Rx 使用查询式的操作符组合和变换数据流

  • 监听:Rx 可以订阅任何可观察的数据流并执行操作

2.2 简化代码

  • 函数式风格:对可观察数据流使用无副作用的输入输出函数,避免了程序里错综复杂的状态

  • 简化代码:Rx 的操作符通常可以将复杂的难题简化为很少的几行代码

  • 异步错误处理:传统的 try/catch 没办法处理异步计算,Rx 提供了合适的错误处理机制

  • 轻松使用并发:Rx 的 ObservablesSchedulers 让开发者可以摆脱底层的线程同步和各种并发问题

2.3 使用 Observable 的优势

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

Observable 通过使用最佳的方式访问异步数据序列填补了这个间隙

单个数据 多个数据
同步 T getData() Iterable getData()
异步 Future getData() Observable getData()

Rx 的 Observable 模型让你可以像使用集合数据一样操作异步事件流,对异步事件流使用各种简单、可组合的操作。

2.3.1 Observable 可组合

对于单层的异步操作来说,Java 中 Future 对象的处理方式是非常简单有效的,但是一旦涉及到嵌套,它们就开始变得异常繁琐和复杂。使用 Future 很难很好地组合带条件的异步执行流程(考虑到运行时各种潜在的问题,甚至可以说是不可能的),当然,要想实现还是可以做到的,但是非常困难,或许你可以用 Future.get(),但这样做,异步执行的优势就完全没有了。从另一方面说,Rx 的 Observable 一开始就是为组合异步数据流准备的。

2.3.2 Observable 更灵活

Rx 的 Observable 不仅支持处理单独的标量值(就像 Future 可以做的),也支持数据序列,甚至是无穷的数据流。Observable 是一个抽象概念,适用于任何场景。Observable 拥有它的近亲 Iterable 的全部优雅与灵活。

Observable 是异步的双向 pushIterable 是同步的单向 pull,对比:

事件 Iterable(pull) Observable(push)
获取数据 T next() onNext(T)
异常处理 throws Exception onError(Exception)
任务完成 !hasNext() onCompleted()
2.3.3 Observable 无偏见

Rx 对于并发性或异步性没有任何特殊的偏好,Observable 可以用任何方式实现,线程池、事件循环、非阻塞 IO、Actor 模式,任何满足你的需求的,你擅长或偏好的方式都可以。无论你选择怎样实现它,无论底层实现是阻塞的还是非阻塞的,客户端代码将所有与 Observable 的交互都当做是异步的。

2.3.4 Observable 是如何实现的?
public Observable getData();
  • 它能与调用者在同一线程同步执行吗?

  • 它能异步地在单独的线程执行吗?

  • 它会将工作分发到多个线程,返回数据的顺序是任意的吗?

  • 它使用 Actor 模式而不是线程池吗?

  • 它使用 NIO 和事件循环执行异步网络访问吗?

  • 它使用事件循环将工作线程从回调线程分离出来吗?

Observer 的视角看,这些都无所谓,重要的是:使用 Rx,你可以改变你的观念,你可以在完全不影响 Observable 程序库使用者的情况下,彻底的改变 Observable 的底层实现。

2.3.5 使用回调存在很多问题

回调在不阻塞任何事情的情况下,解决了 Future.get() 过早阻塞的问题。由于响应结果一旦就绪 Callback 就会被调用,它们天生就是高效率的。不过,就像使用 Future 一样,对于单层的异步执行来说,回调很容易使用,对于嵌套的异步组合,它们显得非常笨拙。

2.3.6 Reactive Programming — 响应式编程

https://en.wikipedia.org/wiki/Reactive_programming

Reactive Programming 是一套编程范式。举个例子:a = b + c。当 b 或 c 变化时,a 自动变化。简单的理解就是建立一个数据流,数据会自动根据数据源变动。

Rx 提供了一系列的操作符,你可以使用它们来 过滤(filter)、选择(select)、变换(transform)、结合(combine) 和 组合(compose) 多个 Observable,这些操作符让执行和复合变得非常高效。

你可以把 Observable 当做 Iterable 的推送方式的等价物,使用 Iterable,消费者从生产者那拉取数据,线程阻塞直至数据准备好。使用 Observable,在数据准备好时,生产者将数据推送给消费者。数据可以同步或异步的到达,这种方式更灵活。

下面的例子展示了相似的高阶函数在 IterableObservable 上的应用:

// Iterable
getDataFromLocalMemory()
  .skip(10)
  .take(5)
  .map({ s -> return s + " transformed" })
  .forEach({ println "next => " + it })

// Observable
getDataFromNetwork()
  .skip(10)
  .take(5)
  .map({ s -> return s + " transformed" })
  .subscribe({ println "onNext => " + it })

Observable 类型给 GOF (the Gang of Four’s Observer pattern) 的观察者模式添加了两种缺少的语义,这样就和 Iterable类型中可用的操作一致了:

  1. 生产者可以发信号给消费者,通知它没有更多数据可用了(对于 Iterable,一个 for 循环正常完成表示没有数据了;对于 Observable,就是调用观察者的 onCompleted() 方法)

  2. 生产者可以发信号给消费者,通知它遇到了一个错误(对于 Iterable,迭代过程中发生错误会抛出异常;对于 Observable,就是调用观察者的 onError() 方法)

有了这两种功能,Rx 就能使 ObservableIterable 保持一致了,唯一的不同是数据流的方向。任何对 Iterable 的操作,你都可以对 Observable 使用。

2.3.7 名词定义

这里给出一些名词的翻译:

  • Reactive 直译为反应性的,有活性的,根据上下文一般翻译为反应式、响应式

  • Iterable 可迭代对象,支持以迭代器的形式遍历,许多语言中都存在这个概念

  • Observable 可观察对象,在 Rx 中定义为更强大的 Iterable,在观察者模式中是被观察的对象,一旦数据产生或发生变化,会通过某种方式通知观察者或订阅者

  • Observer 观察者对象,监听 Observable 发射的数据并做出响应,Subscriber 是它的一个特殊实现

  • emit 直译为发射,发布,发出,含义是 Observable 在数据产生或变化时发送通知给 Observer,调用 Observer 对应的方法,文章里一律译为发射

  • items 直译为项目,条目,在 Rx 里是指 Observable 发射的数据项,文章里一律译为数据,数据项

你可能感兴趣的:(ReactiveX 探索(一)— Rx 介绍)