这是一个非常好的问题。比较这两个世界是非常困难的。Rx是其他语言(如c#、Java或JS)中的响应式扩展的一个端口。
反应式可可的灵感来自函数式反应式编程,但在过去的几个月里,它也被认为是受到反应式扩展的启发。其结果是一个与Rx共享一些东西的框架,但其名称起源于FRP。
首先要说明的是,根据Conal的概念定义,RAC和RxSwift都不是函数式响应式编程实现。从这一点开始,一切都可以简化为每个框架如何处理副作用和其他一些组件。
让我们来谈谈社区和元技术:
RAC is a 3 years old project, born in Objective-C later ported to Swift (with bridges) for the 3.0 release, after completely dropping the ongoing work on Objective-C.
RxSwift is a few months old project and seems to have a momentum in the community right now. One thing that is important for RxSwift is that is under the ReactiveX organization and that all other implementations are working in the same way, learning how to deal with RxSwift will make working with Rx.Net, RxJava or RxJS a simple task and just a matter of language syntax. I could say that is based on the philosophy learn once, apply everywhere.
现在是科技的时候了。
生产/观察实体
RAC 3.0有两个主要实体,Signal和SignalProducer,第一个实体发布事件,不管是否附加订阅者,第二个实体需要开始实际产生信号/事件。这种设计是为了区分冷热观测的乏味概念,这是许多开发人员困惑的根源。这就是为什么差异可以缩小到如何处理副作用。
在RxSwift中,Signal和SignalProducer转换为Observable,这听起来可能令人困惑,但这两个实体在Rx世界中实际上是相同的东西。在RxSwift中使用可观察对象的设计必须考虑它们是热的还是冷的,这听起来可能是不必要的复杂,但一旦你理解了它们的工作原理(热/冷/暖只是订阅/观察时的副作用),它们就可以被驯服。
在这两个世界中,订阅的概念基本上是相同的,有一点不同是RAC引入的,即在发送完成事件之前释放信号时的中断事件。
概括一下,两者都有以下几种事件:
接下来,计算新的接收值
错误,计算一个错误并完成流,取消订阅所有的观察者
完成,将流标记为已完成,取消订阅所有观察者
此外,当一个信号在正确完成或错误完成之前被处理时,RAC已经中断了发送的信号。
手动编写
在RAC中,Signal/SignalProducer是只读实体,它们不能从外部管理,RxSwift中的Observable也是如此。要将Signal/SignalProducer转换为可写实体,必须使用pipe()函数返回一个手动控制的项。在Rx空间中,这是一种不同的类型,叫做Subject。
如果读/写概念听起来不熟悉,可以用未来/承诺做一个很好的类比。Future是一个只读占位符,就像Signal/SignalProducer和Observable,另一方面,Promise可以手动实现,就像pipe()和Subject。
调度器
这个实体在两个世界中是非常相似的,相同的概念,但RAC是串行的,而RxSwift还具有并发调度器。
作文
组合是响应式编程的关键特征。构成流是这两个框架的本质,在RxSwift中它们也被称为序列。
RxSwift中所有的可观察实体都是ObservableType类型的,所以我们用相同的操作符组合了Subject和observable的实例,没有任何额外的考虑。
在RAC空间中,Signal和SignalProducer是两个不同的实体,我们必须在SignalProducer上进行提升,以便能够用Signal的实例组合生成的内容。这两个实体都有自己的操作符,所以当你需要混合东西时,你必须确保某个操作符是可用的,另一方面,你忘记了热/冷的可观察值。
关于这一部分,Colin Eberhardt总结得很好:
看看当前的API,信号操作主要集中在“下一个”事件上,允许你在不同的线程上转换值、跳过、延迟、组合和观察。而信号产生器API主要关注信号生命周期事件(completed, error),操作包括then, flatMap, takeUntil和catch。
额外的
RAC还有Action和Property的概念,前者是一种计算副作用的类型,主要与用户交互有关,后者是在观察值发生变化时执行任务的有趣方式。在RxSwift中,动作再次转换为可观察对象,这在RxCocoa中得到了很好的展示,RxCocoa是iOS和Mac的Rx原语的集成。在RxSwift中,RAC的属性可以转换为变量(或行为主题)。
重要的是要理解,属性/变量是我们必须将命令式世界与响应式编程的声明性本质连接起来的方式,所以有时在处理第三方库或iOS/Mac空间的核心功能时,它是一个基本组件。
结论
RAC and RxSwift are 2 complete different beasts, the former has a long history in the Cocoa space and a lot of contributors, the latter is fairly young, but relies on concepts that have been proven to be effective in other languages like Java, JS or .NET. The decision on which is better is on preference. RAC states that the separation of hot/cold observable was necessary and that is the core feature of the framework, RxSwift says that the unification of them is better than the separation, again it's just about how side effects are managed/performed.
RAC 3.0 seems to have introduced some unexpected complexity on top of the major goal of separating hot/cold observables, like the concept of interruption, splitting operators between 2 entities and introducing some imperative behaviour like start to begin producing signals. For some people these things can be a nice thing to have or even a killer feature, for some others they can be just unnecessary or even dangerous. Another thing to remember is that RAC is trying to keep up with Cocoa conventions as much as possible, so if you are an experienced Cocoa Dev, you should feel more comfortable to work with it rather than RxSwift.
另一方面,RxSwift存在所有的缺点,比如热/冷的可观察对象,但也有响应式扩展的优点。从RxJS, RxJava或Rx。Net到RxSwift是一件简单的事情,所有的概念都是一样的,所以这使得寻找材料非常有趣,也许你现在面临的同样的问题,已经被RxJava中的某人解决了,解决方案可以重新应用,考虑到平台。
选哪一个肯定是个人喜好的问题,从客观的角度不可能说哪一个更好。唯一的办法就是放弃Xcode,同时尝试这两个软件,然后选择一个使用起来更舒服的。它们是类似概念的两个实现,试图实现相同的目标:简化软件开发。