研發與設計專欄
可觀測資料流的兩大工具 PK RxJS observable VS. Mobx observable
前往目錄
observable 與傳統的 promise 和 async/await 有所不同,它能實現更直觀的資料處理、變化監聽等功能。

此文章建議要有 observable(一種處理非同步工作的工具)概念再來閱讀,若無此概念的朋友,可先搜尋 30 天精通 RxJS (05): 建立 Observable(一)及 30 天精通 RxJS(23): Subject、BehaviorSubject、ReplaySubject、 AsyncSubject 這兩篇文章,讓閱讀者能短時間內有基本概念。

以前在處理非同步的工作、資料傳遞(像是跟 server API 拿資料、等待結果回傳再進行下一 步動作),常用的有 promise 和 async await, observable 跟他們最大的差異,就是能夠實現 functional,取得 response 後可直接進行資料 parsing ,直觀好懂。實現 change listener,一旦訂閱,即可監聽未來所有數值的改變。
 

RxJS observable 用起來像這樣:

 
由上可知,我們在 DataStore 先設定了一 個可供訂閱的 dataSubject、初始值為 0。 ButtonComponent 在 constructor 運作後就會訂閱 dataSubject 的所有變動,一旦變動就把最新的數值存到 data 裡面,當按鈕按下去,會去呼叫 dataStore.update() 讓 dataSubject 存放的數值加一,進而觸發 data 改變。
 
這裡要注意到一點是,dataStore.dataSubject 只要有任何更新,所有訂閱他的元件都會拿取到最新的數值,這就是 observable 強大的地方, 將所有與 dataStore 相關連的元件的資料溝通綁定在一起,不會再有一個動作改 A 元件結果沒改到 B 元件的情況。
 

Mobx observable 用起來像這樣:

 
看起來 Mobx 較為直觀好懂,因為他藉由 decorator @ 讓變數有了可被觀測的能力。 這裡注意一下我沒有使用 observe (dataStore. data, ...) 因為 observe 只支援觀測物件!如果要觀測 primitive value 要使用 observable box,文章之後也會提到。可在 Mobx 官方文件查閱 boxed values 章節,有詳細介紹 box 使用方法。
 
但接下來將會遇到 Mobx 的弱點,我們設定一個情境,要觀測資料開始 loading 與 loading 完成的過程,加入 isDataLoading 標 記著資料開始改變到改變結束的狀態。
 

RxJS:

 

Mobx:

 
這裡會有個情況導致錯誤,observe 只有在 dataStore.data 改變時才會觸發,當我們執行 this.dataStore.update(this.data) 因為數值沒改變,observe 無法觸發,將導致 isDataLoading 一直為 true。必須改寫成:
 
 
這裡可看見 dataObservable 是個可觀測的 box 物件,便能使用observe (dataStore. dataObservable, ...) 並且不論數值是否更新,dataObserve.set(v) 都會觸發 observe 變動。
 
綜合以上可做個結論,一般在處理單純的資料同步上,Mobx 提供相當簡易好用的 coding style,而若牽涉到動作開始與結束、 並非單純只要觀測資料數值的情境下, RxJS 提供了較簡單的作法。
 
可在不同的情境上,自由取用合適的工具。譬如 data cache,user 不需知道 data cache 何時開始與結束,就可優先考慮 Mobx ;而頁面資料 API,幾乎都要提示 user 並在載入前後顯示 loading 狀態,就可考慮 observable。