序言
首先先介紹兩個概念由缆, Reactive Extensions 和Functional Reactive Programming(FRP)叹坦。
Reactive Extensions
Reactive Extensions原來是由微軟提出的一個綜合了異步和基于事件驅動編程的庫包巨朦,使用可觀察序列和LINQ-style查詢操作盏触。
事件驅動編程
事件玩徊,事件代表過去發(fā)生的事件谍失,事件既是技術架構方面的概念,也是業(yè)務概念嫡丙。以事件為驅動的編程模型稱為事件驅動架構EDA
忠售。
EDA
是一種以事件為媒介,實現組件或服務之間最大松耦合的方式迄沫。傳統(tǒng)面向接口編程是以接口為媒介稻扬,實現調用接口者和實現接口者之間的解耦,就是我們平常開發(fā)中的請求網絡數據羊瘩,解析數據泰佳,但是這種解耦程度不是很高盼砍,如果接口發(fā)生變化,雙方的代碼都需要變動逝她,而事件驅動則是調用者和被調用者互相不知道對方浇坐,兩者只和中間消息隊列耦合。就像古人結婚一樣黔宛,男女雙方不見面近刘,需要了解什么對方的情況只能通過媒人來了解,當然這個例子舉的不太合適臀晃。下面用個圖直接明了的表明一下這種方式觉渴。
事件驅動有以下特征:
1.生產者producer發(fā)生實時事件
2.推送通知
3.生產者發(fā)送消息面
4.消費者consumer立即響應
5.事件和命令是有區(qū)別的
事件驅動還有異步特征,傳統(tǒng)方法就像我們iOS中調用什么什么method()徽惋,是一種同步模型案淋,必須等待調用者執(zhí)行完這段代碼后才可以執(zhí)行其他代碼。而對于異步模型來說险绘,事件生產者發(fā)出事件后踢京,不必等待回應,可以繼續(xù)執(zhí)行下面的代碼宦棺。
當然瓣距,還有一個重要的概念就是不代表使用了消息系統(tǒng)架構的都叫做EDA,還有面向服務驅動架構的SOA里面也使用了消息系統(tǒng)作為ESB代咸,服務端的東西我不了解蹈丸,我們做前端的也不需要過多的了解。
Functional Reactive Programming(FRP)
Functional Reactive Programming(FRP)叫做函數式反應式編程侣背,是一種和事件流有關的編程方式白华,關注導致狀態(tài)值改變的行為事件慨默,一系列事件組成了事件流贩耐。
FRP是更加有效率的處理事件流,而無需顯式去管理狀態(tài)厦取。
具體來說潮太,FRP包括兩個核心觀點:
1.事件流,離散事件序列
2.屬性虾攻,代表模型連續(xù)的值
一系列事件是導致值發(fā)生變化的原因铡买。
總述
Rx是Reactive Extensions 的一部分,其他的開發(fā)語言比如C#霎箍,Java奇钞,JS等也有Rx。
RAC是 受 Functional Reactive Programming(FRP) 啟發(fā)漂坏,但是在最近一段時間里景埃,他們提到也受到Reactive Extensions 的啟發(fā)媒至。最終結果就是一個從Rx借鑒了一些東西,但是有著源自FRP名聲的一個框架谷徙。
無論是Rx還是RAC拒啰,都不是真正意義上的FRP。
RAC是一個有著三年歷史的項目了完慧,從最初的OC開始谋旦,到3.0開始支持swift,現在直接停止了對OC的維護和更新屈尼。
Rx是嚴格按照ReactiveX這個組織的規(guī)定開發(fā)的册着,所以如果真正學會了RxSwift,再去學習什么Rx.net,Rx.js,Rx.java鸿染,都是灑灑水了指蚜,只是語法上的差異而已。
分析
RAC3.0主要有兩個實體涨椒,signal
和 SignalProducer
摊鸡。
signal
無論是否綁定了訂閱者都可以發(fā)布事件。
SignalProducer
要有一個信號或者事件產生才會觸發(fā)蚕冬。
這兩個區(qū)別是為了區(qū)分冷信號和熱信號免猾。what?你說你不知道什么是熱信號囤热,什么是冷信號猎提。好吧
熱信號是主動的,即使你沒有訂閱事件旁蔼,它仍然會時刻推送锨苏。而冷信號是被動的,只有當你訂閱的時候棺聊,它才會發(fā)送消息伞租。
熱信號可以有多個訂閱者,是一對多限佩,信號可以與訂閱者共享信息葵诈。而冷信號只能一對一,當有不同的訂閱者祟同,消息會從新完整發(fā)送作喘。
在RxSwift中,signal
和 SignalProducer
變成了Observable
晕城,這兩個實體在Rx中是一個東西泞坦。在RxSwift里創(chuàng)建Observables不需要考慮是冷信號還是熱信號。冷/熱信號是當你subscribing/observing產生的副作用砖顷。
對于訂閱的概念兩者基本是一樣的贰锁。在RAC里有一點小的區(qū)別主之,RAC可以中斷一個事件,當信號被disposed
李根,即使在事件發(fā)送完成信號之前槽奕。
下面說一下兩者訂閱時共有的吧
Next
處理新收到的值
Error
處理一個錯誤,結束整個流房轿,對所有的觀察者取消訂閱
Complete
標記整個流已經完成粤攒,取消所有觀察者的訂閱
另外RAC會在收到一個disposed Signal 后中斷,即使沒有收到complete或者error囱持。
在RAC中夯接,Signal/SignalProducer都只是只讀的實體,他們不能從外部被改變纷妆,RxSwift中的Observable也是如此盔几。如果要把Signal/SignalProducer改變成可以手動改寫的實體的話,你只能通過調用管道pipe()
函數返回一個可以改動的對象掩幢。在Rx中逊拍,這是一個不同的類型叫做Subject
。
RAC是連續(xù)的际邻,串行芯丧,而Rx可以支持并發(fā)。
在Rx中所有的observable的實體的類型都是ObservableType
世曾,所以我們可以輕松的用同一個操作符將Subject和Observable的實例組合起來缨恒。
在RAC中,Signal和SignalProducer是兩種不同的對象轮听。我們必須把SignalProducer轉換成Signal后才能compose由Signal實例產生的信號骗露。這兩個對象擁有各自的操作符。所以當你需要混合使用它們時血巍,你必須考慮到某種操作符是否是兩者通用萧锉,這個時候你也不必關心冷/熱的處理了。
現在signal的API主要關注在處理next
上藻茂,讓你可以改變值驹暑,skip
玫恳,delay
辨赐,combineLatest
并且在不同的線程里觀察值。signal producer的API主要處理信號的生命周期事件(completed京办,error)掀序,和一些這樣的操作:then
,flatMap
惭婿,takeUntil
和catch
不恭。
skip
跳過幾個信號叶雹,不接受
delay
延遲發(fā)送next
combineLatest
將多個信號合并起來,并且拿到各個信號的最新的值换吧,必須每個合并的signal至少都有過一次sendNext折晦,才會觸發(fā)合并的信號。
then
用于連接兩個信號沾瓦,當第一個信號完成满着,才會連接then返回的信號
flatMap
用于把源信號內容映射成一個新的內容
takeUntil
獲取信號直到某個信號執(zhí)行完成
catch
用于封裝一個錯誤處理機制的signal,也就是當signal1出現了錯誤贯莺,將創(chuàng)建一個新的錯誤處理signal2风喇,完成后并處理訂閱者的流程,舉個例子缕探,如果要為服務器上的某個商品點贊+1魂莫,但是出現了網絡不通,這個時候就要把UserDefault里的值減1
在RAC中還有Action
和Property
的概念爹耗。Action是一種處理副作用的類型耙考,主要和用戶交互相關。Property用于觀察當執(zhí)行一個任務后值改變了的情況潭兽。
在Rx中Action
也會轉變成一個Observable
類型琳骡。RAC中的Property
對應于Rx中的Variable
或者BehaviourSubject
結論
通過本文大家可以自己抉擇是用Rx呢還是RAC,個人意見是如果你的項目是主OC讼溺,不妨使用RAC楣号,因為RAC在cocoa領域是很成熟的,如果項目是主Swift怒坯,不如嘗試下Rx炫狱,一勞永逸。