Redux 處理非同步 Action

2022-03-10 05:23:25 字數 4385 閱讀 2404

redux-promise-utils是乙個基於redux-thunkredux-actions的工具,符合 fsa 規範,方便開發者處理非同步 action,減少大量冗餘的 template **。

redux 一開始的設計就是用於處理同步的 action。通過呼叫 action 函式後 dispatch 返回的 type 和 payload ,最終交由 reducer 處理。reducer 匹配到相應的 type 並進行處理。

說到 redux 處理非同步 action,最為人熟知的就是redux-thunkredux-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-thunkredux-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是把資料從應用...