RxJS 是什麼?! 觀察者、被觀察的對象

Ken
8 min readMay 1, 2021

--

Observable, Observer, Subscribe

所有權: 昆蟲 Life 秀

Observable 是 Rx 最重要的一個角色!

請凝視上方的動畫 3 秒,將這些搬著方糖的螞蟻印在腦海裡,我將嘗試以故事的角度試著解釋這些名詞,假如小明有個暑假作業:

老師請小明在一段時間內,觀察螞蟻搬運了多少食物,並將結果記錄在記錄簿上

一般情況下,小明沒辦法預期會 有多少螞蟻走過、每隔多久 會經過一隻螞蟻,但小明知道在這段期間,只要每一隻螞蟻經過,他就會看螞蟻身上有多少顆方糖。

假設在一個架空世界,全球總共只有4隻螞蟻、以及他們搬運多少顆糖是明確的,這些行為就可以被事先記載起來的,就寫成底下這樣:

上面僅記載了螞蟻世界,每隻螞蟻搬運方糖的顆數,但跟小明的暑假作業還無關(你不去觀察、你就不會知道。所以小明不知道)。這頂多是老師在放假前,形容螞蟻世界可能會長什麼樣子,到時候還有賴小明自己去觀察,然後寫進紀錄本裡。

小明不知道螞蟻什麼時候會出現,只知道看到螞蟻要紀錄下他背上的糖有幾顆。

螞蟻世界的螞蟻們,也不知道到底有誰這麼無聊,在觀察他們。

兩者如何產生聯繫,唯有透過訂閱來聯繫彼此

訂閱之後,兩者的連結產生了,每隻螞蟻經過時,都會跟小明說一聲,小明自己再來決定螞蟻到了後要幹嘛(也就是寫進記錄本裡)。

現在我們終於可以讓小明做點事情了!!!所以在螞蟻世界裡,當每次有螞蟻經過任何人面前,螞蟻就把方糖數量告訴小明或任何生物觀察學家,讓他們可以好好辦事 (丟進 最初的 ant.next 裡面) 。

小明或諾貝爾生物觀察學家,知道這個數字後,想要做的事情也不一樣,畢竟層次不同XD,所以每個人的 next 裡要做什麼事,可能也不一樣。

code sandbox demo

為了方便說明,所以在前面的範例命名比較不恰當,我們在這裡來重新定義一下螞蟻世界,其實螞蟻世界裡被執行的 next 是屬於觀察者的,不是屬於螞蟻。螞蟻做為被觀察的對象,每隻螞蟻只會把自己搬了幾顆方糖,告訴觀察者(有些人也稱他們為訂閱者),所以將原本的參數 ant 改名 叫做 observer / subscriber。

const ants$ = new Observable(observer => {
observer.next(0);
observer.next(1);
observer.next(1);
observer.next(5);
observer.complete();
});

小結

其實螞蟻就像是一連串的資料流,這些螞蟻組成了螞蟻世界(Collection),我們不知道他們什麼時候會到來、會來多少隻,但是每隻來了,小明就要做一些事情(Callback)。而如何讓螞蟻與小明聯繫,則是透過訂閱(Subscribe)來達成。

  1. Observable: 螞蟻世界的每隻螞蟻們背上的方糖
Represents the idea of an invokable collection of future values or events.

2. Observer:小明、生物學家或任何對螞蟻世界有興趣的人們

Is a collection of callbacks that knows how to listen to values delivered by the Observable

Subscribe是什麼?同步、非同步?

而這個神秘螞蟻世界,同時也支持同步、非同步。

codesandbox demo

就好比我們的 Promise,拿到一個結果後,會將這個值傳給 resolve callback,只是 Observable 可以處理多個值;Promise 處理完一次結果就停止了。

如同 Promise 的 resolve, reject, finally,Observable也可以執行3種 callback function,是 next, error 還有 complete。

如同 Promise ,實際做什麼是在 then( ) 執行時決定;Observalbe 實際做什麼是在 subscribe( ) 執行時決定。

A subscribe call is simply a way to start an "Observable execution" and deliver values or events to an Observer of that execution. (by RxJS doc)

而相較於 Function(同步、回傳單一值),Observable 也能同步執行,並且可以回傳「多」個值。

小結

Function:當被呼叫時,可以同步回傳「單一」個值
Promise:可能或不會在最後回傳 「單一」個值,給 resolve callback 執行,但一定會呼叫 resolve 或 reject 其中一個 callback一次。
Observable:被呼叫時,可以同步非同步回傳 「多」個值,給 next callback 執行或遇到錯誤時呼叫 error callback。

這裡的 single, multiple 或許用單次、多次來形容,更為恰當。

這裡的推拉 Push/ Pull 是兩種不同的 Protocol

什麼是 Pull ?什麼是Push?

首先我們需要先定義 Producer, Consumer 這兩個名詞,才好解釋 Pull/Push。
Producer 是指產出資料的這個人;Consumer則是使用這個資料的人。有了這兩個假定,我們便可以開始解釋!

Producer 只知道產出資料,對 Producer 而言,它不知道誰會使用這個資料、什麼時候被使用;Consumer 則是決定什麼時候要拿這個資料來使用。我們稱做 Pull!

Consumer pull data from Producer

反而言之

Consumer只知道使用資料,對 Consumer 而言,它不知道什麼時候能使用這個資料,只知道拿到這個資料後要做些什麼;Producer 則決定什麼時候產出、並且通知 Consumer 可以使用了。我們稱做 Push!

Producer push data to Consumer

以上一個表格而言,Function / Promise / Observable 都是 Producer,負責產出資料的狠角色
Function 沒辦法決定何時產出資料,被別人執行時,就會同步回傳一個結果,所以是 Pull / Single Return;

Promise 則是根據自己的步調來產生資料,產出資料後就會通知 resolve / reject,回傳單一個結果,所以是 Push / Single Return;

Observable則是完全依照自己的步調來發出資料,並且可以產出多個結果,所以是 Push / Multiple Return。

RxJS 這個 Library ,則是提供許多底層已實作好的 Observable, 及其他對應的 types, operators 供 JavaScript 開發者能輕易建立各式各樣的 Observables。

目前小明只看到每隻螞蟻背上的糖,並且對螞蟻背上的糖做點事情(召喚console,每次顯示在控制台),距離完成暑假作業還有一段路。我們還必須加總計算等。

預計下一次將介紹常見 Observables 的種類、使用及能達成什麼同步、非同步應用。

參考資料

RxJS 官方文件

如果這篇文章對你有幫助,請幫我拍手一下
你的拍手及分享是對我最大鼓勵與書寫下篇文章的動力

1下 閱。
5–10下 你認為這篇文章還不錯。
11–20下 你認為這篇貼文對你很有幫助。
21–40下 你非常喜歡這篇貼文,覺得實用。
40–50下 希望我可以多分享關於 Rx 相關的文章

--

--