呼叫 API 顯示 Nested Promise
若 API 遵循 RESTful 精神設計,常會第一個 API 僅回傳 id
,若要取得其值就要呼叫第二個 API,也就是所謂 N + 1,本文分別以 Aysnc Await、Promise Chain 與 RxJS 三種寫法示範。
失くすものさえない今が強くなるチャンスよ
若 API 遵循 RESTful 精神設計,常會第一個 API 僅回傳 id
,若要取得其值就要呼叫第二個 API,也就是所謂 N + 1,本文分別以 Aysnc Await、Promise Chain 與 RxJS 三種寫法示範。
實務上常會將眾多 Observable 加以合併,concat()
除了會將 Observable 合併外,還會依照 Argument 順序合併,直到一個 Observable 完成,才會繼續合併下一個 Observable。
RxJS 有提供 exhaustMap()
,卻沒提供 exhaustMapTo()
,但我們可以自行建立 exhaustMapTo()
。
很多 FP 語言與 FP Library 都有內建 pipe()
Operator 只選取 Object 部分 Property,但 RxJS 只內建了 pluck()
,但我們也可自行建立 pick()
Operator。
RxJS 提供了 pluck()
直接取得 Object 的 Property,若要取得部分 Property,RxJS 並沒有提供直接 Operator,此時可使用 RxJS 的 map()
+ Ramda 的 pick()
實現。
實務上有些 API 呼叫有順序性,無論 Promise 或 Observable 都是 Asynchronous,不保證回傳順序也不保證一定成功,因此處理這些 Asynchronous 動作並不像 Synchronous 般簡單。
由於 RxJS 的 Declarative 與 Stream 特性,因此在處理 Asynchronous Error 與處理 Rejected Promise 觀念不太一樣,重點在維持 Stream 不要死掉,讓下一個 Asynchronous Value 能正常發出。
DOM 要配合 RxJS,直覺都會使用 v-stream
配合 DOM Event,事實上也能使用 watchAsObservable()
朝 data 下手。
由於 DOM Event 為 Observable,API Request 亦為 Observable,若 Table 亦必須由 N + 1 Query 呼叫其他 API 取得資料,這就造成了 Observable of Observable of Observable 的三層 Higher Order Observable,這該如何使用 RxJS 實現呢 ?
實務上有些資料會不斷變動,因此希望每隔一段時間就重新呼叫 API 讀取資料,為避免 asynchronous 資料尚未完成就呼叫 API,我們會希望回傳成功後經過一段時間再呼叫,這種常見的需求該如何使用 RxJS 實現呢 ?
除了可以由 RxJS 的 Operator 建立 Observable 外,我們也可使用 map()
從既有 Observable 繼續建立新 Observable。
Front-end 兩大 Asynchronous 就是 DOM Event 與 API Request,實務上常將這兩個 Asynchronous 視為 Observable 一起處理,這導致了 Higher Order Observable 出現,RxJS 提供了 mergeMap()
、concatMap()
、switchMap()
與 exhaustMap()
處理,本文探討 exhaustMap()
。
Front-end 兩大 Asynchronous 就是 DOM Event 與 API Request,實務上常將這兩個 Asynchronous 視為 Observable 一起處理,這導致了 Higher Order Observable 出現,RxJS 提供了 mergeMap()
、concatMap()
、switchMap()
與 exhaustMap()
處理,本文探討 concatMap()
。
Front-end 兩大 Asynchronous 就是 DOM Event 與 API Request,實務上常將這兩個 Asynchronous 視為 Observable 一起處理,這導致了 Higher Order Observable 出現,RxJS 提供了 mergeMap()
、concatMap()
、switchMap()
與 exhaustMap()
處理,本文探討 mergeMap()
。
DOM Event 為 Observable,而 API 回傳資料亦為 Observable,若在 DOM Event 發起 API Request,這就會產生 Highr Order Observable,RxJS 提供了多個 Operator 可在不同場景使用。
RxJS 與 Ramda 同屬 Functional Library,RxJS 特色在於 Asynchronous 部分,而 Ramda 則在於 Synchronous,事實上 RxJS 與 Ramda 可搭配 Vue 一起使用。
若說 Ramda 是 FP 對於 Synchronous 解決方案,RxJS 則是 FP 在 ECMAScript 對於 Asynchronous 解決方案。Vue 官方已經將 RxJS 整合進 Vue,稱為 Vue-rx。
Asynchronous 為 ECMAScript 無法逃避的課題,該如何才能以相同 Mental Model 同時處理 Synchronous 與 Asynchronous 呢 ?
從 API 回傳雖然是單一 Observable,若顯示時是在不同處時,我們可將單一 Observable 產生多個 Observable 分開顯示。
由於 RESTful API 特性,實務上常會遇到無法單一 API 就能拿到結果,必須連續呼叫多次 API,本文分別以 Async Await、Promise Chain、Ramda 與 RxJS 示範,可比較其背後不同 Mental Model 。
為避免 User 產生重複 API Request,將 Button Disabled 是一種方式,也可改用 exhaustMap()
實現。
既然 API 回傳結果與 DOM event 都是 Observable,可將兩個 Observable 合併成單一 Observable 顯示。
RxJS 因為是 Reactive,因此由 Observable 建立其他 Observable 時,也會重發新 API Request 反應最新資料,若我們想重複使用既有 Observable 且不建立新 API Request,可使用 share()
達成需求。
由於讀取 API 為 Asynchronous 行為,若 Data 未及時回應,User 可能會再次按下 Button 而造成 Mutiple API Request,因此比較好的方式是當按下 Button 後立即將 Button Disabled,等 API 回傳完整後才將 Button Enabled。
若想 Input 輸入值就直接打 API,而不要透過 Button Click,傳統會寫在 input
Event,但若想每隔一段時間才取得 Input 值減少 API Request,也就是所謂 Debounce,自行要實作就沒那麼簡單,但透過 RxJS 可簡單實現。
前端的難點之一是讀取 API 時,回傳為 Promise,這是 Asynchronous 行為;若使用 RxJS 可視為 Observable,以 Stream 方式處理 API 回傳資料。
雖然 API 會回傳 Observable,但其實骨子裡都還是 ECMAScript 的 Array 與 Object,實務上我們常只需要 Object 中部分 Property 即可,這在 RxJS 該如何做呢 ?
若兩個 Observable 各自產生而非相依,但又必須隨時間一起合作時,可使用 combineLatest()
各自取得其最新值然後一起合作。
若 API 遵循 RESTful 精神設計,常會第一個 API 僅回傳 id
,若要取得其值就要呼叫第二個 API,也就是所謂 N + 1 Query,RxJS 對這種常見需求有很漂亮寫法。
Data Binding 是 Vue 的一大特色,但我們也可使用 watchAsObservable()
將 data 轉成 Observable 以 RxJS 處理。
若多個 DOM Element 的處理邏輯相同,只有 Data 不同,可共用相同的 Observable 並傳入不同 Template Data 即可。
RxJS 常見的應用之一就是將 DOM Event 視為 Event Stream,本文以 RxJS 實現萬年老梗 Counter。
RxJS 是 ECMAScript 以 FP 處理 Asynchronous 的神兵利器,透過 Quokka 我們可以更快速測試與學習 RxJS。