# W_Rxjs note - rxjs 是用來處理非同步而產生的工具 - 彈珠圖,資料流在運行 Operators 的圖像化 - observable 為觀察對象,它還沒有作用,直到 subscribe 訂閱才會處理值 - pipe() 只是加工 observable,最後還是要對它進行訂閱 ## 觀念 ### 串流 - 資料流,是一個動詞,在資料還未發送完畢時,會一直輸出,就是資料流,不斷運行者,但還未顯示直到訂閱 - 訂閱就是開啟資料流,讓資料流出,並且可以獲取資料顯示 - 取消訂閱就是把資料流關閉,不論是資料在何種狀態,立即中止 ### pipe 為甚麼不能直接接 subscribe ? 設計思維,因為 pipe 做完還有機會重用邏輯。如果後面直接接續訂閱,那此 observable 邏輯就不能重用。除非是已經確定這個 observable 只用在單一事件情況下,便可直接用 subscribe ### 疑問與未解之謎 - Observable of Observable ? - 如何判斷回傳的是 Observable ? - 可以用 Map 系列或是 All 系列來自動訂閱,避免巢狀結構 ? - cold hot observable ## flattening operator aka 展開運算符,可以講回傳為 Observable 的值展開取的內部的值 flattening 三兄弟 | 目的 | 用法 | | ------- | ------------- | | 只要最新的 | `switchAll()` | | 要全部平行執行 | `mergeAll()` | | 要依序執行 | `concatAll()` | ## Observable vs Subject - 兩者都有相同之處 ### Observable (一對一,靜態) - 建立物件同時就決定資料流向 - 每個訂閱者都會得到獨立資料流,又稱單播 ### Subject (一對多,動態的) - 在產生物件後才決定資料流向 - 每次事件發生時,就會同步傳遞給所有訂閱者,稱為多播 - 每次都直接執行資料流 ## Observable 他是 ## Operator 有分兩種 Creation Operators vs Pipeable Operators - creation 是用來建立新的 observable,不必透過 new Observable 建立 - pipeable 是將 observable 加工的 operator,必須透過 pipe() 來包裝加工方法 ## Operator 運算子 像 js 方法,其中有一些類似 array。專們給 observable 加工的方法 ### tap - 處理 side effect ### subject - ### debunceTime - 遏止使用這過度使用按鈕的機制 ```javascript! //這是練習建立 「輸入框輸入文字 → 等 500ms → 將文字轉成大寫後印出」的 RxJS 程式。 import { fromEvent, Observable } from 'rxjs'; import { map, debounceTime } from 'rxjs/operators'; // const div = document.createElement('div'); // div.textContent = 'this just test'; // document.body.appendChild(div); // div.style.background = 'orange'; // div.style.marginTop = '20px'; //在 document 建立 input const input = document.createElement('input'); document.body.appendChild(input); //在 js 操作 html、css input.placeholder = 'test for nothing'; input.style.padding = '5px'; input.style.borderRadius = '6px'; //建立 rxjs 事件 const input$ = fromEvent(input, 'input'); //建立事件串流,但還沒有使用 const action$ = input$.pipe( debounceTime(500), map((e) => e.target.value.toUpperCase()) ); //訂閱事件 開啟串流 action$.subscribe((data) => { console.log(data); }); ``` ### of - 把資料一個個送出 ### from - 跟 of 有點像,差別是他會列出陣列與物件內容,而 of 是把之料直接傳出,並非一個個釋出 ## Subscribe 訂閱 只要使用他就是開啟資料流,開啟訂閱,即便是用變數包裝,它也是開啟狀態 ```javascript! const subscription = timeInterval$.subscribe((data) => { console.log(`時間會持續輸出偶數: ${data}`); }); ``` ### unsubscribe() 它是 subscribe 的方法,我在實作時發現我用 observable$ 來使用 unsubscribe() 所以導致錯誤。 ```javascript! setTimeout(() => { subscription.unsubscribe(); // ✅ 取消訂閱 console.log('已取消訂閱'); }, 10000); ``` ### merge 會將時間差的融合 ```javascript! const test1$ = interval(1000).pipe( tap(data=> console.log(`A${data}`) ) const test2$ = interval(3000).pipe( tap(data=> console.log(`B${data}`) ) const test3$ = interval(5000).pipe( tap(data=> console.log(`c${data}`) ) merge(test1$,test2$,test3$).subscribe(data=>{ console.log(data) }) // A1 // A2 // A3B1 // A4 // A5C1 ``` ### zip 跟 merge 很相似,不同的是它會同時印出來,所以第一位會等最後一位,依照時間順序 ## partition 它會依據我們設定的規則函式拆成兩個 observable ```javascript! import { of, partition } from 'rxjs'; const shit$ = of(1, 2, 3, 4, 5, 6, 7, 8); const [a1$, a2$] = partition(shit$, (data) => data % 2 === 0); a1$.subscribe((data) => console.log(data)); a2$.subscribe((data) => console.log(data)); //2 //4 //6 //8 //1 //3 //5 //7 ```