比較RAC和RxSwift

weixin_34290000發表於2017-03-27

序言

首先先介紹兩個概念, Reactive ExtensionsFunctional Reactive Programming(FRP)。

Reactive Extensions

Reactive Extensions原來是由微軟提出的一個綜合了非同步和基於事件驅動程式設計的庫包,使用可觀察序列和LINQ-style查詢操作。

事件驅動程式設計

事件,事件代表過去發生的事件,事件既是技術架構方面的概念,也是業務概念。以事件為驅動的程式設計模型稱為事件驅動架構EDA
EDA是一種以事件為媒介,實現元件或服務之間最大鬆耦合的方式。傳統面向介面程式設計是以介面為媒介,實現呼叫介面者和實現介面者之間的解耦,就是我們平常開發中的請求網路資料,解析資料,但是這種解耦程度不是很高,如果介面發生變化,雙方的程式碼都需要變動,而事件驅動則是呼叫者和被呼叫者互相不知道對方,兩者只和中間訊息佇列耦合。就像古人結婚一樣,男女雙方不見面,需要了解什麼對方的情況只能通過媒人來了解,當然這個例子舉的不太合適。下面用個圖直接明瞭的表明一下這種方式。

3873966-422d73b167f36cb7.png
EDA

事件驅動有以下特徵:

1.生產者producer發生實時事件
2.推送通知
3.生產者傳送訊息面
4.消費者consumer立即響應
5.事件和命令是有區別的

事件驅動還有非同步特徵,傳統方法就像我們iOS中呼叫什麼什麼method(),是一種同步模型,必須等待呼叫者執行完這段程式碼後才可以執行其他程式碼。而對於非同步模型來說,事件生產者發出事件後,不必等待迴應,可以繼續執行下面的程式碼。

當然,還有一個重要的概念就是不代表使用了訊息系統架構的都叫做EDA,還有面向服務驅動架構的SOA裡面也使用了訊息系統作為ESB,服務端的東西我不瞭解,我們做前端的也不需要過多的瞭解。

Functional Reactive Programming(FRP)

Functional Reactive Programming(FRP)叫做函式式反應式程式設計,是一種和事件流有關的程式設計方式,關注導致狀態值改變的行為事件,一系列事件組成了事件流。
FRP是更加有效率的處理事件流,而無需顯式去管理狀態。
具體來說,FRP包括兩個核心觀點:
1.事件流,離散事件序列
2.屬性,代表模型連續的值
一系列事件是導致值發生變化的原因。

總述

Rx是Reactive Extensions 的一部分,其他的開發語言比如C#,Java,JS等也有Rx。
RAC是 受 Functional Reactive Programming(FRP) 啟發,但是在最近一段時間裡,他們提到也受到Reactive Extensions 的啟發。最終結果就是一個從Rx借鑑了一些東西,但是有著源自FRP名聲的一個框架。
無論是Rx還是RAC,都不是真正意義上的FRP。
RAC是一個有著三年曆史的專案了,從最初的OC開始,到3.0開始支援swift,現在直接停止了對OC的維護和更新。
Rx是嚴格按照ReactiveX這個組織的規定開發的,所以如果真正學會了RxSwift,再去學習什麼Rx.net,Rx.js,Rx.java,都是灑灑水了,只是語法上的差異而已。

分析

RAC3.0主要有兩個實體,signalSignalProducer
signal無論是否繫結了訂閱者都可以釋出事件。
SignalProducer要有一個訊號或者事件產生才會觸發。
這兩個區別是為了區分冷訊號和熱訊號。what?你說你不知道什麼是熱訊號,什麼是冷訊號。好吧

熱訊號是主動的,即使你沒有訂閱事件,它仍然會時刻推送。而冷訊號是被動的,只有當你訂閱的時候,它才會傳送訊息。
熱訊號可以有多個訂閱者,是一對多,訊號可以與訂閱者共享資訊。而冷訊號只能一對一,當有不同的訂閱者,訊息會從新完整傳送。

在RxSwift中,signalSignalProducer變成了Observable,這兩個實體在Rx中是一個東西。在RxSwift裡建立Observables不需要考慮是冷訊號還是熱訊號。冷/熱訊號是當你subscribing/observing產生的副作用。

對於訂閱的概念兩者基本是一樣的。在RAC裡有一點小的區別,RAC可以中斷一個事件,當訊號被disposed,即使在事件傳送完成訊號之前。
下面說一下兩者訂閱時共有的吧
Next
處理新收到的值
Error
處理一個錯誤,結束整個流,對所有的觀察者取消訂閱
Complete
標記整個流已經完成,取消所有觀察者的訂閱
另外RAC會在收到一個disposed Signal 後中斷,即使沒有收到complete或者error。

在RAC中,Signal/SignalProducer都只是只讀的實體,他們不能從外部被改變,RxSwift中的Observable也是如此。如果要把Signal/SignalProducer改變成可以手動改寫的實體的話,你只能通過呼叫管道pipe()函式返回一個可以改動的物件。在Rx中,這是一個不同的型別叫做Subject

RAC是連續的,序列,而Rx可以支援併發。

在Rx中所有的observable的實體的型別都是ObservableType,所以我們可以輕鬆的用同一個操作符將Subject和Observable的例項組合起來。
在RAC中,Signal和SignalProducer是兩種不同的物件。我們必須把SignalProducer轉換成Signal後才能compose由Signal例項產生的訊號。這兩個物件擁有各自的操作符。所以當你需要混合使用它們時,你必須考慮到某種操作符是否是兩者通用,這個時候你也不必關心冷/熱的處理了。
現在signal的API主要關注在處理next上,讓你可以改變值,skipdelaycombineLatest並且在不同的執行緒裡觀察值。signal producer的API主要處理訊號的生命週期事件(completed,error),和一些這樣的操作:thenflatMaptakeUntilcatch
skip
跳過幾個訊號,不接受
delay
延遲傳送next
combineLatest
將多個訊號合併起來,並且拿到各個訊號的最新的值,必須每個合併的signal至少都有過一次sendNext,才會觸發合併的訊號。
then
用於連線兩個訊號,當第一個訊號完成,才會連線then返回的訊號
flatMap
用於把源訊號內容對映成一個新的內容
takeUntil
獲取訊號直到某個訊號執行完成
catch
用於封裝一個錯誤處理機制的signal,也就是當signal1出現了錯誤,將建立一個新的錯誤處理signal2,完成後並處理訂閱者的流程,舉個例子,如果要為伺服器上的某個商品點贊+1,但是出現了網路不通,這個時候就要把UserDefault裡的值減1

在RAC中還有ActionProperty的概念。Action是一種處理副作用的型別,主要和使用者互動相關。Property用於觀察當執行一個任務後值改變了的情況。
在Rx中Action也會轉變成一個Observable型別。RAC中的Property對應於Rx中的Variable或者BehaviourSubject

結論

通過本文大家可以自己抉擇是用Rx呢還是RAC,個人意見是如果你的專案是主OC,不妨使用RAC,因為RAC在cocoa領域是很成熟的,如果專案是主Swift,不如嘗試下Rx,一勞永逸。

相關文章