redux-promise-utils
是乙個基於redux-thunk
和redux-actions
的工具,符合 fsa 規範,方便開發者處理非同步 action,減少大量冗餘的 template **。
redux 一開始的設計就是用於處理同步的 action。通過呼叫 action 函式後 dispatch 返回的 type 和 payload ,最終交由 reducer 處理。reducer 匹配到相應的 type 並進行處理。
說到 redux 處理非同步 action,最為人熟知的就是redux-thunk
。redux-thunk
是乙個 middleware,它可以在 reducer 延遲處理 action,並在非同步的相應**中再 dispatch action。所以我們可以認為 redux-thunk 其實不是專門處理非同步用的 middleware,而是可能會延遲執行 dispatch 的函式。
在大多數的redux-thunk
規範中,對乙個請求需要定義三種action,發起請求前,請求成功後,請求失敗後。一般**都是如下所示。
// constant/actiontype.js
export default
// data/action.js
import action_type from '../constant/actiontype'
import * as api from './api'
// start fetch
export function fetchaction(options) )
return api.fetchlist(options)
.then((response) =>
})})
.catch((response) =>
})})
}}// data/reducer.js
import action_type from '../constant/actiontype'
const initstate = {}
export function reducer(state = initstate, action)
}
乙個簡單的請求 action 需要如此多的 template **。一旦業務量起來後,幾十上百個的非同步請求都需要複製貼上大量**,實在是非常的難受。
當開發者都感受到痛苦後,自然會出頭解決問題,redux-promise
就是解決方案。
redux-promise
提供了乙個簡單建立 promise action 的方法,並提供配套的 middleware 處理 promise 化的 action。整套**精簡了特別多,大致如下。
// data/action.js
import from 'redux-promise'
import * as api from './api'
import action_type from '../constant/actiontype'
export const fetchaction = createaction(action_type.fetch_list, api.fetchlist)
// data/reducer.js
import from './action.js'
import action_type from '../constant/actiontype'
const initstate = {}
return (state = initstate, action) => else
return state
default:
return state
}}/*
當然在基於 redux-actions,使用 handleaction 是可以省略 actiontype.js 檔案和定義的 action_type 的。
這裡為了更清晰展現大家熟悉的 switch case 式的 reducer 就沒有展示出來了。
*/
這一看,**似乎精簡了許多,不需要對乙個介面定義三個 actiontype 了。但是 redux-promise 只能處理兩種狀態了,非同步後的成功/失敗態。實際使用上,似乎也沒什麼影響,畢竟 redux 天然支援同步 action,所以你就在調非同步 action 前再調乙個同步 action ,那個 action 來當作fetch_list_start
來使用。
所以我們把定義乙個非同步 action 和對應的三個 actiontype ,轉變為定義兩個 action 和對應的 actiontype,且破壞了乙個非同步 action 的內聚性,導致本身乙個非同步 action 造成的 state 變化,被拆成了兩個去維護,實在有失優雅和**相應的維護性。
綜上所述,我認為redux-thunk
還是乙個更為合理的方案,我們是否能基於redux-thunk
然後降低我們過於冗餘的**呢。我們來看看到底redux-thunk
有哪些麻煩的操作我們需要來優化。
每次都需要執行 promise 方法後,內部手動去 dispatch 各個狀態給 reducer 進行處理。
乙個非同步 action 需要定義三個特定的 actiontype。
需要維護乙個的 actiontype 檔案,並提供給 action / reducer 使用。
// data/action.js
import from 'redux-promise-utils'
import * as api from './api'
export const fetchaction = createpromiseaction('fetchlist', api.fetchlist)
// data/reducer.js
import from 'redux-promise-utils'
import from './action'
const initstate = {}
const reducer = createreducer(initstate)
// 獲取同步資料
.which(sync_action, (state, action) => )
// 獲取非同步資料
.asyncwhich(fetchaction, ,
success(state, action) ,
fail(state, action)
})// 構建 redux 需要的 reducer 方法
.build()
export default reducer
**精簡了許多,上述的三個問題都 say goodbye 了。除了 reducer 不再使用 switch case 模式去處理,並沒有特別多的區別。那到底 createpromiseaction / createreducer 做了哪些處理,下面會講到。
redux-promise-uitls
核心是基於redux-thunk
和redux-actions
。
先來看看 createpromiseaction,核心就是內建三個執行狀態,並基於 promise 下自動 dispatch 相應的狀態。所以內部會按一定的規則,根據提供的 type 派生出三種狀態,分別是$_start
/$_success
/$_failed
。得益於redux-thunk
,即使不用配套提供的 createreducer 處理,也可以手動處理這三種狀態。但使用了 createreducer 則會更加順暢,包括不需要再維護 actiontype,不用單獨處理派生出的三種狀態。
而 createreducer 內部,對asyncwhich(type, handleroptions)
捕獲到的 action,會根據 start/success/fail 三個函式自動處理,不需要寫多餘的 type。which(type, handler)
捕獲的則是普通的同步函式,和以往的 reducer 寫法是一樣的。
createreducer 會對 type 執行一次type.tostring()
,而 createpromiseaction 借鑑redux-actions
的 createaction 一樣,會重寫type.tostring
方法,所以也不需要再獨立維護一套 actiontype.js 相應的配置檔案。
這些操作都是為了讓開發者可以逃離大部分無意義的 template **,來提高每日的編碼體驗。
github: redux-promise-utils
Redux 非同步操作
最近狀態不太好,學習redux的非同步操作花的時間比想象的多,這裡盡量清晰簡要的表述一下在redux中怎麼實現非同步操作。先回顧一下同步操作 我們用redux執行同步的時候,都是先發起乙個dispatch actioncreator 1.先在actioncreator 中生成乙個action物件。2...
Redux非同步方案實現
一 不借用第三方庫實現redux非同步 場景建立 先來個很常見的場景,在http請求之前我們一般會用loading元件來表示資料正在請求,等http請求結束就關閉loading。下圖所示的是http請求的3種狀態 上述場景如果不使用redux狀態管理器,我們會使用react的state或hooks特...
如何理解Redux中的action
例子1 const redux function couter state 0,action const store createstore couter 然後呼叫store.dispatch 之後用store.getstate便去獲取值,得到的是1.action 的定義 action是把資料從應用...