官方文檔鏈接:http://reactivex.io/documentation/observable.html
1.前言
ReactiveX的概念是惩坑,一個觀察者訂閱一個被觀察者,然后觀察者響應(yīng)被觀察者產(chǎn)生/傳遞的每一個事件或事件隊列丐膝。這種模式有利于并發(fā)操作捐友,當(dāng)?shù)却挥^察者產(chǎn)生/傳遞事件時淫半,不需要阻塞線程,而是創(chuàng)建觀察者匣砖,隨時準(zhǔn)備響應(yīng)被觀察者將來時間做出的事情科吭。
這節(jié)介紹什么是響應(yīng)模式,什么是觀察者和被觀察者(以及觀察者如何訂閱被觀察者)脆粥。以后將介紹如何使用各種被觀察者的操作符來連接被觀察者和改變他們行為砌溺。文檔附帶解釋用的圖表,下面示例反映圖表如何展示被觀察者和它的轉(zhuǎn)換:
2.被觀察者
可以理解為數(shù)據(jù)源变隔,內(nèi)部封裝了一系列事件等待自己來調(diào)用规伐,從而傳遞出去(產(chǎn)生事件)。
參考的文章:
- Single — 只產(chǎn)生一個事件的特定版本的被觀察者
- Rx Workshop: Introduction
- Introduction to Rx: IObservable
- Mastering observables (來自Couchbase的文檔)
- 2 minute introduction to Rx by Andre Staltz (“假設(shè)被觀察者是異步的不可變的數(shù)組”)
- Introducing the Observable by Jafar Husain (JavaScript視頻教程)
- Observable object (RxJS) by Dennis Stoyanov
- Turning a callback into an Rx Observable by @afterecho
3.異步處理
在許多軟件開發(fā)任務(wù)中匣缘,或多或少期望猖闪,編寫的指令按照書寫順序,依次執(zhí)行肌厨,逐步完成培慌。但在ReactiveX中,許多指令可以并行執(zhí)行柑爸,并由觀察者按任意順序捕獲相應(yīng)結(jié)果吵护。與方法調(diào)用相比,先定義被觀察者,然后用觀察者訂閱的模式來檢索和轉(zhuǎn)換數(shù)據(jù)馅而,隨時準(zhǔn)備著在某個時間點(diǎn)捕獲和響應(yīng)事件的發(fā)生祥诽。這種方式有一個好處,當(dāng)有一堆互不依賴的任務(wù)時瓮恭,讓它們同時開始比等待上一個結(jié)束再開始下一個要好雄坪,因?yàn)樗腥蝿?wù)完成消耗的時間只由耗時最長的任務(wù)決定。
有不少術(shù)語來描述這種異步編程和設(shè)計的模型屯蹦,本文將采用:觀察者訂閱被觀察者维哈。被觀察者通過調(diào)用觀察者的方法來傳遞事件和發(fā)送通知給自己的觀察者。在后面的文章中登澜,有時會稱呼“觀察者”為“訂閱者”阔挠、“監(jiān)視者”、“響應(yīng)者”帖渠,這種模型通常也被稱為“響應(yīng)模式”谒亦。
4.創(chuàng)建觀察者
下面的例子將使用類似Groovy的偽代碼,因?yàn)镽eactiveX在多種語言下都有實(shí)現(xiàn)空郊。
普通方法調(diào)用——不是那種異步的份招、ReactiveX中典型的并行調(diào)用——流程就像這樣:
- 調(diào)用一個方法。
- 一個變量存儲那個方法返回的值狞甚。
- 用那個變量和它的新值做一些有意義的事锁摔。
// make the call, assign its return value to `returnVal`
returnVal = someMethod(itsParameters);
// do something useful with returnVal
在異步模型中,流程更像這樣:
- 定義一個方法哼审,使用異步調(diào)用返回的值做一些有意義的事谐腰;這個方法是觀察者的一部分。
- 定義異步調(diào)用本身作為被觀察者涩盾。
- 通過觀察者訂閱被觀察者來關(guān)聯(lián)兩者(這一步引發(fā)被觀察者產(chǎn)生事件)十气。
- 繼續(xù)業(yè)務(wù)邏輯;每當(dāng)調(diào)用返回時春霍,觀察者方法將開始對返回的值(被觀察者產(chǎn)生的事件)執(zhí)行操作砸西。
// defines, but does not invoke, the Subscriber's onNext handler
// (in this example, the observer is very simple and has only an onNext handler)
def myOnNext = { it -> do something useful with it };
// defines, but does not invoke, the Observable
def myObservable = someObservable(itsParameters);
// subscribes the Subscriber to the Observable, and invokes the Observable
myObservable.subscribe(myOnNext);
// go on about my business
4.1.觀察的事件
若觀察者要通過subscribe()
方法與被觀察者連接起來,需實(shí)現(xiàn)下面方法的一些子集:
onNext()
每當(dāng)被觀察者產(chǎn)生一個事件址儒,它將調(diào)用這個方法芹枷,并使用它產(chǎn)生的事件作為參數(shù)。
onError()
被觀察者調(diào)用這個方法莲趣,表明它未能生成預(yù)期的數(shù)據(jù)鸳慈,或者遇到一些其它的錯誤,將不會接著調(diào)用onNext()
或onCompleted()
方法喧伞。onError()
方法使用導(dǎo)致錯誤的指示走芋,作為它的參數(shù)绩郎。
onCompleted()
被觀察者調(diào)用onNext()
方法之后,且沒有遇到任何問題翁逞,當(dāng)結(jié)束事件的產(chǎn)生時嗽上,它調(diào)用這個方法。
被觀察者可能調(diào)用onNext()
方法零次或多次熄攘,之后可能調(diào)用onCompleted()
或onError()
方法中的一種,作為最終調(diào)用彼念。這里約定一下挪圾,文章中調(diào)用onNext()
方法稱為“產(chǎn)生事件”,而調(diào)用onCompleted()
或onError()
方法稱為“發(fā)送通知”逐沙。
def myOnNext = { item -> /* do something useful with item */ };
def myError = { throwable -> /* react sensibly to a failed call */ };
def myComplete = { /* clean up after the final response */ };
def myObservable = someMethod(itsParameters);
myObservable.subscribe(myOnNext, myError, myComplete);
// go on about my business
可以參考這篇文章 Introduction to Rx: IObserver
4.2.取消訂閱
有一些ReactiveX的實(shí)現(xiàn)哲思,定義了專門的觀察者,即訂閱者吩案,實(shí)現(xiàn)了取消訂閱的方法棚赔。調(diào)用這個方法表明,訂閱者不再關(guān)心當(dāng)前訂閱的任何一個被觀察者徘郭。那些被觀察者(如果它們沒有被其它觀察者訂閱)之后可以選擇停止產(chǎn)生新的事件靠益。取消訂閱的結(jié)果,將會回溯觀察者訂閱被觀察者時使用的操作鏈残揉,并且將導(dǎo)致鏈中的每個節(jié)點(diǎn)停止傳遞事件(封裝在被觀察者對象中)胧后。但這個過程不能保證立即發(fā)生,被觀察者有可能產(chǎn)生并嘗試傳遞事件抱环,即使沒有觀察者再訂閱它壳快,仍能持續(xù)一段時間。
4.3.命名規(guī)則
每種特定語言對ReactiveX的實(shí)現(xiàn)镇草,有許多共同點(diǎn)眶痰,但沒有規(guī)范的命名標(biāo)準(zhǔn)。因?yàn)樗鼈兌加凶约旱拿?xí)慣梯啤,而且這些名字在不同的上下文中有不同的含義竖伯,或者不符合特定實(shí)現(xiàn)語言的習(xí)慣。
5.被觀察者類型
由被觀察者的類型条辟,決定什么時候產(chǎn)生它自己的事件隊列黔夭。熱類型,在它被創(chuàng)建時會開始產(chǎn)生事件羽嫡,之后任何觀察者再訂閱它本姥,可能從隊列中間的某處開始捕獲。冷類型杭棵,則相反婚惫,等到有觀察者訂閱它才開始產(chǎn)生事件氛赐,所以能保證觀察者從開始捕獲整個隊列。
在ReactiveX的一些實(shí)現(xiàn)中先舷,有一些被稱為可連接的被觀察者艰管。這樣的被觀察者不會開始產(chǎn)生事件直到它的connect()
方法被調(diào)用,不管是否有觀察者已經(jīng)訂閱它蒋川。
6.總結(jié)
理解被觀察者和觀察者牲芋,不過才剛剛接觸ReactiveX的概念。它們本身只能算是對標(biāo)準(zhǔn)觀察者模式(若有不清楚此模式的捺球,后期會在設(shè)計模式文集中加以說明)輕微的擴(kuò)展缸浦,以便適合處理一系列事件。
ReactiveX真正的核心氮兵,是通過操作符改變裂逐、組合和控制被觀察者產(chǎn)生的事件隊列。尤其允許將異步事件的隊列組合在一個聲明中泣栈,保留回調(diào)所有的優(yōu)點(diǎn)卜高,但沒有回調(diào)嵌套處理的缺點(diǎn)。下一節(jié)將詳細(xì)給大家講解這些神奇的操作符南片。