这是一个很好的问题。比较两个世界是非常困难的。 Rx 是响应式扩展在其他语言(如 C#、Java 或 JS)中的一个端口。
Reactive Cocoa 受到 Functional Reactive Programming 的启发,但在过去几个月中,也被指出也受到 Reactive Extensions 的启发。结果是一个框架,它与 Rx 共享一些东西,但名称起源于 FRP。
首先要说的是,根据Conal's definition 的概念,RAC 和 RxSwift 都不是 Functional Reactive Programming 实现。从这一点开始,一切都可以简化为每个框架如何处理副作用和其他一些组件。
让我们谈谈社区和元技术的东西:
- RAC 是一个已有 3 年历史的项目,诞生于 Objective-C,后来在完全放弃了 Objective-C 正在进行的工作后移植到 Swift(带有桥接器)的 3.0 版本。
- RxSwift 是一个几个月前的项目,现在似乎在社区中有一股势头。对 RxSwift 很重要的一件事是在 ReactiveX 组织下,并且所有其他实现都以相同的方式工作,学习如何处理 RxSwift 将使使用 Rx.Net、RxJava 或 RxJS 成为一项简单的任务,并且只需语言语法的问题。我可以说这是基于一次学习,无处不在的理念。
现在是技术方面的时候了。
生产/观察实体
RAC 3.0 有 2 个主要实体,Signal 和 SignalProducer,第一个实体发布事件,无论是否附加订阅者,第二个实体需要 start 才能实际产生信号/事件。创建这种设计是为了将冷热可观察对象的繁琐概念分开,这一直是许多开发人员困惑的根源。这就是为什么差异可以减少到它们如何管理副作用。
在 RxSwift 中,Signal 和 SignalProducer 转换为 Observable,这听起来可能令人困惑,但这两个实体在 Rx 世界中实际上是同一个东西。必须在 RxSwift 中创建带有Observables 的设计,考虑它们是热的还是冷的,这听起来可能是不必要的复杂性,但是一旦你了解它们是如何工作的(同样热/冷/暖只是副作用,而订阅/观察)它们可以被驯服。
在这两个世界中,订阅的概念基本相同,RAC 引入的一点点不同是interruption 事件是在发送完成事件之前处置Signal。
回顾一下两者都有以下类型的事件:
-
Next,计算新收到的值
-
Error,计算错误并完成流,取消订阅所有观察者
-
Complete,将流标记为已完成取消订阅所有观察者
RAC 还具有 interrupted,当 Signal 在正确完成或出现错误之前被处置时发送。
手动书写
在 RAC 中,Signal/SignalProducer 是只读实体,它们不能从外部管理,RxSwift 中的 Observable 也是如此。要将Signal/SignalProducer 转换为可写实体,您必须使用pipe() 函数返回手动控制项。在 Rx 空间中,这是一个不同的类型,称为 Subject。
如果读/写概念听起来不熟悉,可以与Future/Promise 做一个很好的类比。 Future 是只读占位符,如Signal/SignalProducer 和Observable,另一方面,Promise 可以手动实现,如pipe() 和Subject。
调度器
这个实体在两个世界中非常相似,相同的概念,但是 RAC 是仅串行的,相反 RxSwift 还具有并发调度程序。
作曲
组合是响应式编程的关键特征。组合流是这两个框架的本质,在 RxSwift 中它们也被称为 sequences。
RxSwift 中的所有可观察实体都是ObservableType 类型,因此我们使用相同的运算符组合Subject 和Observable 的实例,无需任何额外关注。
在 RAC 空间中,Signal 和 SignalProducer 是 2 个不同的实体,我们必须在 SignalProducer 上使用 lift 才能组合使用 Signal 的实例生成的内容。这两个实体有自己的运算符,因此当您需要混合时,您必须确保某个运算符可用,另一方面您忘记了热/冷 observables。
关于这部分,Colin Eberhardt总结得很好:
查看当前的 API,信号操作主要集中在“下一个”事件上,允许您在不同线程上转换值、跳过、延迟、组合和观察。而信号生产者 API 主要关注信号生命周期事件(完成、错误),操作包括 then、flatMap、takeUntil 和 catch。
额外
RAC还有Action和Property的概念,前者是计算副作用的类型,主要与用户交互有关,后者在值发生变化时观察值执行任务时很有趣.在 RxSwift 中,Action 再次转换为 Observable,这在 RxCocoa 中得到了很好的展示,这是一个适用于 iOS 和 Mac 的 Rx 原语的集成。 RAC 的Property 可以在 RxSwift 中翻译成Variable(或BehaviourSubject)。
重要的是要了解Property/Variable 是我们必须将命令式世界与反应式编程的声明性本质联系起来的方式,因此在处理第三方库或核心功能时有时是一个基本组件iOS/Mac 空间。
结论
RAC 和 RxSwift 是两个完全不同的野兽,前者在 Cocoa 领域有着悠久的历史和很多贡献者,后者相当年轻,但依赖于已被证明在 Java 等其他语言中有效的概念、JS 或 .NET。哪个更好的决定取决于偏好。 RAC 指出热/冷 observable 的分离是必要的,这是框架的核心特性,RxSwift 说它们的统一比分离更好,这再次只是关于如何管理/执行副作用。
RAC 3.0 似乎在分离热/冷 observables 的主要目标之上引入了一些意想不到的复杂性,例如中断的概念、在 2 个实体之间拆分运算符以及引入一些命令式行为(如start)开始产生信号。对于某些人来说,拥有这些东西可能是一件好事,甚至是杀手级功能,而对于另一些人来说,它们可能只是不必要的,甚至是危险的。另一件要记住的事情是,RAC 试图尽可能地跟上 Cocoa 的约定,所以如果你是一个有经验的 Cocoa 开发者,你应该觉得使用它比使用 RxSwift 更舒服。
另一方面,RxSwift 具有所有缺点,例如热/冷 observables,但也有反应式扩展的优点。从 RxJS、RxJava 或 Rx.Net 迁移到 RxSwift 是一件简单的事情,所有的概念都是相同的,所以这使得寻找材料变得非常有趣,也许你现在面临的同样的问题,已经被 RxJava 中的某个人解决了,并且解决方案可以根据平台重新应用。
选哪个绝对是个人喜好问题,从客观的角度无法判断哪个更好。唯一的方法是启动 Xcode 并尝试这两种方法,然后选择使用起来感觉更舒服的一种。它们是相似概念的 2 个实现,试图实现相同的目标:简化软件开发。