# RxJS講義 RxJS為一種資料串流為基礎,宣告式的程式設計方式,以ReactiveX概念的JavaScript實作。ReactiveX一系列基於可觀察的資料流API適合操作非同步程式設計,結合***觀察、迭代、函式***等主要的設計概念。 ## 資料V.S. 資料串流(streaming) 資料為單向筆資訊取得,資料串流唯一連串的資料及運串結果,且隨著時間觀念而不段變化,補充說明:(時間來的不固定,資料回/傳完畢,client端自動斷線)。 舉例情境:影片串流(進影音平台讓每個人同等頻寬,可同時服務的人更多。)、直播、續傳軟體(續傳的行為可以說串流資料)、股票即時資訊(金融類相關資訊)、線上遊戲(LOL),資料舉例:圖檔。 Q:假如同時抓20個工單,一個工單有10件商品,總共200個商品,client端要處理大量處理,發出220 http request/response,所有資料取回得到畫面上,這樣的行為是串流嗎?一口氣request到伺服器,20發出去,回來必須依序回來,會怎麼操作? A:非同步的這種操作,就可以利用RxJS來處理及組合資料串流的相關問題。 ### 命令式(Imperative) 強調執行實作細節,傳統的FOR迴圈 ### 宣告式(declarative) 強調執行的過程與目標,可讀性較高,RxJS就是宣告式方式寫法。 JavaScript非同步程式設計,會將程式碼工作放在等待區,等執行完畢後,再決定是否繼續非同步的程式碼。 舉例API:DOM(CLICK、CHANGE、INPUT、SUBMIT),遠端伺服器抓取資料用(XMLHttpRequest、 fetch),Timers(setTimeout、setInterval) **結論** 非同步程式碼放置等待區,不會因等待而造成畫面阻塞(non-blocking I/O) 執行順需不一定依序由上而下,如何處理接收非同步成一大重點 當非同步行為越來越多,如何整合成為新議題。 ## 觀察者模式Observer Pattern 偵測資料變更的責任反轉。 * 觀察者(observer) notify當目標資料變更,由目標主動呼叫觀察者的notify方法,告知資料變更了。 * 目標(subject) * notifyObservers,用來通知所有目前的觀察者資料變更,也就是呼叫所有觀察者的notify方法 * addObserver,將某個物件加入觀察者清單 * deleteObserver,將某個物件從觀察者清單移除 ## 迭代模式Iterator Pattern 使用for迴圈走訪所有元素,樹狀結構的資料,使用遞迴走訪所有樹狀資料。 使用迭代器模式hasNext(),next(),就能達成以上這些狀態。 ## 函式程式設計Functional Programming OOP物件導向(Angular)、FP函數式(RxJS),兩種混搭的方式。 * 函式最基本的運算單位,避免使用程式狀態及可變物件 * 程式狀態 當函式觀點來看,狀態可分內部狀態(函式內),外部狀態(函式外),若內部改變外部物件,這樣就不太妥當,會無法預測改變原本的值。 純函式Pure Function,相同輸入值的運算結果得到一樣的輸出值,函式內不無任何函式副作用(side effect)操作。函式副作用舉例:HTTP呼叫、檔案存取I/o、DOM操作、console.log。 * 可變物件(mutable object) JavaScript都是可變物件,原始型別不具可變性(immutable),最常使用ES6展開運算式(Spread syntax)語法,物件型別具有可變形(mutable)。 以Angular為例,進行變更偵測時,預設會使用髒檢查(dirty check),深入物件每個屬性比較是否有資料變更,檢查成本較為龐大,如何避免?就是使用Pure Function。 * λ運算式(函式本身可不具名匿名函式,λ運算式可接受函式當作輸入(引數)輸出(傳出值) ## 函式程式設計技巧 ### 組合(compose) 可讓一系列清單依照先後順序執行,避免巢狀方式,讓每個韓式的輸出值皆為下一個輸入值,閱讀順序符合一般數學運算。 ### 管線(pipe)與組合相似 但將執行順序反過來,符合一般程式設計師對於程式碼閱讀由上到下的習慣 Tap function,傳入一個函式fn做為參數,包含data參數的內部函式,執行fn(data),呼叫完畢後直接回傳參數。 * 強調執行結果 * 高階函式(Higher-order function)是一個函式,至少符合以下條件:傳入一個或多個函式物件,必須回傳一個函式物件。不用去管低階函式如何實作,直接回傳另一個函式。像是柯里化(currying) ## Functional Programming結論 優點,適度抽象畫,拆多個函式,重用性更高 缺點,過度抽象畫,造成閱讀困難,多運算邏輯拆開,效能較低 設計建議,多撰寫純函式,宣告式思考,善用高階函式,柯理化,將實作細節委外,提高函式共用性,結合組合及管線運用,寫出更加宣告式的程式碼。 ## RxJS核心角色 Observable可被觀察的物件,Observer觀察者,Subscription訂閱物件,缺一不可。Operators運算子,Subject觀察目標,Scheduler排程控制器,對主要三大項進行操作處理。 進行步驟:建立Observable,組合Observable,監聽Observable ### 彈珠圖Marble Diagram 參考官方文件 * [rxjs](https://rxjs.dev/) * [rxmarbles](https://rxmarbles.com/) ![彈珠圖](https://i.imgur.com/8IPMo75.png) ## Observable 基礎 在RxJS最基本建立資料流的方法 * Observable類別 * Subject類別 * BehaviorSubject類別 * AsyncSubject類別 ## RxJS運算子 Operators種類 ## 資料來源 * [rxjs](https://rxjs.dev/operator-decision-tree) * [完整API](https://rxjs.dev/api?type=function) ## 可觀察物件的簡易分類Cold Observable v.s. Hot Observable * Cold Observable 當有訂閱發生,才啟動資料流,每次執行會得到一樣的資料流程,每個訂閱彼此獨立 * Hot Observable 當Observable建立當下運作中的資料流,新事件產生時,會推送當下訂閱的觀察者,目標都是同一份運作 ###### tags: `Angular` `RxJS`