標籤:

從redux-saga想到的前端多範式問題

從redux-saga想到的前端多範式問題

來自專欄用戶中心 | User Oriented7 人贊了文章

昨天看了一下redux-saga,感覺API有點複雜,所以用rxjs做了個簡化版。

redux-saga的核心思想很簡潔:把一個業務流程的所有部分寫在一起。實現上則是使用了generator允許多個返回值的的特性。

例如,如果要實現一個共三步的註冊嚮導,分別需要輸入email、輸入密碼和確認license,而且每步完成才能進入下一階段,用saga的思路就可以寫成(偽代碼):

async function* wizard() { for(let isEmailLegal = false; !isEmailLegal;){ // 循環直到用戶輸入了合法的email const email = await inputedEmail() const validateResult = await validateEmail(email) if(validateResult.isLegal){ isEmailLegal = true yield email // 把email存在store } else { yield showError // 顯示一個錯誤信息 } } yield step2 // 顯示下一步的界面 for(let isPasswordLegal = false; !isPasswordLegal;){ // 略。寫法類似上一個for } yield step3 await confirmedLicense() yield submitInfo // 嚮導結束}

這個邏輯用其他非同步方案(例如redux-observable或者redux-trunk)也完全可以實現,但是,使用saga實現有著以下其他方案所沒有的優點:

  • 一個業務流程的邏輯可以完全寫在一個函數中,聚合度很高
  • 代碼的閱讀過程是從上到下,貼近需求文檔
  • 用try/catch就可以實現異常處理,降低了學習成本

同時,實際操作中,也存在一些不適合saga的用例:

  • 不存在觸發事件的邏輯,例如緩存多個事件等待一起處理
  • 與時間相關的邏輯,例如上一條中的情況,以及常見的輸入事件截流

redux-saga對這些問題的解決方案是自帶了一些工具函數,例如race。但是,這些函數跟saga的核心思想無關,也不具有跟rxjs同等的描述能力;更重要的是,有些問題的描述就是聲明式的,redux-saga指令式的寫法無法簡潔地描述問題。

不難想到,redux-saga(指令式)和redux-observable(聲明式)結合,才能實現最好的效果(感興趣的話,可以考慮本文開頭提到的小庫)。

因此又想到一個問題:rxjs對非同步問題的解決能力非常強,可能是目前前端最強大的非同步方案。但即使rxjs,也無法描述所有的情況,有些情況使用saga來描述要更加簡潔。從另一個角度,因為redux/react的設計相當自由,我們才有機會思考「saga和observable兩種模式結合會怎樣」這個問題。

這也是很多框架存在的問題:銀彈並不存在,實踐中總是會出現新問題,而且新問題可能需要不同的範式才能解決。當出現框架作者沒想過或者不接受的情況的時候,用戶該怎麼辦呢?saga和observable就能優雅地描述所有邏輯嗎?

我沒有信心作出回答。但是,只要redux/react的高度解耦設計允許多範式的存在,想必到時候總是能找到解決方案的。


推薦閱讀:

從零搭建webpack4+React工程(二)
為什麼你的Angular雙向數據綁定會失效?
TypeScript 如何完美地書寫 React 中的 HOC?
dva系列3 - UI與數據邏輯的粘合層
React v16 與 Webpack v4 的多特性模板項目

TAG:React | Redux | RxJS |