redux-observable/Redux-Saga
關於 redux side effects
在開發前端 SPA 的時候,我們有一大半的時間再處理異步動作,更具體來說的話就是網路請求(ajax)。
在一般的使用情境下的流程大概會是這樣的
處理從請求開始到請求結束的流程在 redux only 下,我們可以透過 store.subscribe 去監聽 actions,然後進一步的調用異步方法,並在異步方法結束的時候 dispatch 相對應的 action。
- lastAction 需要自己在 reducer 內實作,可以參考到 https://github.com/reactjs/redux/issues/580
但如果註冊為 middleware 而不是 subscribe store 的話,不但可以取得 store/action 甚至進而調整輸出的 action。
到這邊,其實光是用來舉例的單單一個 action 在不管是 subscribe store 或是 middleware 裡面的實作,從冗長的 switch 判斷就知道這樣的解決方式是一個不好的方案。
redux-thunk
redux-thunk 是 redux 異步處理 middleware 的開拓者,他非常簡單易懂 (不過其實在接觸thunk初期的時候我根本不知道 。dispatch
從哪來,有興趣的人可以看一下 redux-thunk source code,極短)
但在更為複雜的架構下就顯得較為無力招架,所以開發者們從最原初的
thunk 出發,開始尋求其他的解決方案。
處理 side effects 的其他 middleware 中較為亮眼的則有 redux-observable,與 redux-sage,基本上兩者處理 side effects 都非常優秀,並且相似,而這篇文章則是想要整理些比較做個筆記以及提供給各位做選擇上的參考。
那麼先從簡單的介紹開始切入核心:
以 RxJS 為主,核心概念為將 action 視為 stream,透過 observe action 並且轉換為另一個 action 來處理異步請求。
Actions in, actions out
,在這邊附上從官方文件來的簡單範例。
而對 RxJS 並不熟悉的各位,Rx 系列的文件非常齊全,推薦可以透過 RxMarbles 的視覺化 Operator 來學習。
Netflix 工程師 Jay Phelps 的 talk 也非常有幫助,並且非常風趣 (Jay: open source的第一步,就是要做一個好 Logo)。
以 ES6 generator 為核心主軸,利用 yield 和 redux saga 所提供的一些 helpers 來處理 async actions。
我們可以從官方的範例裡看到 generator 的運用,而學習 redux-saga 基本上就等同於學習 ES6 generator 的過程。
By doing so, these asynchronous flows look like your standard synchronous JavaScript code. (kind of like async/await, but generators have a few more awesome features we need)
Compare side by side
因為 redux-sage 或是 redux-observabl 其實兩者的差異並沒有到天差地遠的大,那就跟選用顯卡一樣各取所需,接下來就依照一些使用情境來讓各位能更清楚的了解兩者的差異。
Launch Up
saga - Watcher + Worker
observable - Type & Observable
Cancelable
saga
observable
Throttling
saga
observable
Debouncing
saga
observable
Retrying
saga
observable
Conclusion
redux-observable | Redux-Saga | |
---|---|---|
Learning Path |
|
|
Style | Declarative | Imperative |
Pros/Cons |
|
|
另外有其他更棒的 side by side comparison 例子歡迎大家討論提供 😉