响应式编程是一种基于异步数据流概念的编程模式。数据流就像一条河:它可以被观测,被过滤,被操作,或者为新的消费者与另外一条流合并为一条新的流。
响应式编程的一个关键概念是事件。事件可以被等待,可以触发过程,也可以触发其它事件。事件是唯一的以合适的方式将我们的现实世界映射到我们的软件中:如果屋里太热了我们就打开一扇窗户。同样的,当我们更改电子表(变化的传播)中的一些数值时,我们需要更新整个表格或者我们的机器人碰到墙时会转弯(响应事件)。
今天,响应式编程最通用的一个场景是UI:我们的移动App必须做出对网络调用、用户触摸输入和系统弹框的响应。在这个世界上,软件之所以是事件驱动并响应的是因为现实生活也是如此。
函数响应式编程是一个来自90年代后期受微软的一名计算机科学家Erik Meijer启发的思想,用来设计和开发微软的Rx库。
Rx 是微软.NET的一个响应式扩展。Rx借助可观测的序列提供一种简单的方式来创建异步的,基于事件驱动的程序。开发者可以使用Observables模拟异步数据流,使用LINQ语法查询Observables,并且很容易管理调度器的并发。
Rx让众所周知的概念变得易于实现和消费,例如push方法。在响应式的世界里,我们不能假装作用户不关注或者是不抱怨它而一味的等待函数的返回结果,网络调用,或者数据库查询的返回结果。我们时刻都在等待某些东西,这就让我们失去了并行处理其他事情的机会,提供更好的用户体验,让我们的软件免受顺序链的影响,而阻塞编程。
下表列出的与.NET 枚举相关的.NET Observable
.NET Observable | 一个返回值 | 多个返回值 |
---|---|---|
Pull/Synchronous/Interactive | T |
IEnumerable<T> |
Push/Asynchronous/Reactive | Task<T> |
IObservable<T> |
push方法把这个问题逆转了:取而代之的是不再等待结果,开发者只是简单的请求结果,而当它返回时得到一个通知即可。开发者对即将发生的事件提供一个清晰的响应链。对于每一个事件,开发者都作出相应的响应;例如,用户被要求登录的时候,提交一个携带他的用户名和密码的表单。应用程序执行登录的网络请求,接下来将要发生的情况有:
正如你用push方法所看到的,开发者不需要等待结果。而是在结果返回时通知他。在这期间,他可以做他想做的任何事情:
Netflix在2012年开始意识到他们的架构要满足他们庞大的用户群体已经变得步履维艰。因此他们决定重新设计架构来减少REST调用的次数。取代几十次的REST调用,而是让客户端自己处理需要的数据,他们决定基于客户端需求创建一个专门优化过的REST调用。
为了实现这一目标,他们决定尝试响应式,开始将.NET Rx迁移到JVM上面。他们不想只基于Java语言;而是整个JVM,从而有可能为市场上的每一种基于JVM的语言:如Java、Closure、Groovy、Scala等等提供一种新的工具。
2013年二月份,Ben Christensen 和 Jafar Husain发在Netflix技术博客的一篇文章第一次向世界展示了RxJava。
主要特点有:
正如.NET,RxJava Observable 是push 迭代的等价体,即pull。pull方法是阻塞并等待的方法:消费者从源头pull值,并阻塞线程直到生产者提供新的值。
push方法作用于订阅和响应:消费者订阅新值的发射,当它们可用时生产者push这些新值并通知消费者。在这一点上,消费者消费了它们。push方法很明显更灵活,因为从逻辑和实践的观点来看,开发者只需忽略他需要的数据是来自同步还是异步;他的代码将仍然起作用。
从纯Java的观点看,RxJava Observable类源自于经典的Gang Of Four的观察者模式。
它添加了三个缺少的功能:
Observables和Iterables共用一个相似的API:我们在Iterable可以执行的许多操作也都同样可以在Observables上执行。当然,由于Observables流的本质,没有如Iterable.remove()这样相应的方法。
Pattern | 一个返回值 | 多个返回值 |
---|---|---|
Synchronous | T getData() |
Iterable<T> |
Asynchronous | Future<T> getData() |
Observable<T> getData() |
从语义的角度来看,RxJava就是.NET Rx。从语法的角度来看,Netflix考虑到了对应每个Rx方法,保留了Java代码规范和基本的模式。
本章中,我们初步探索了响应式的世界。从微软的.NET到Netflix的RxJava,我们了解了Rx是如何诞生的,我们也了解到传统的方法与响应式方法相比之间的相似和不同。
下一章,我们将学习到Observables是什么,以及如何创建它并把响应式编程应用到我们的日常编码中去。