文章首發於個人博客 https://github.com/mcuking/bl...相關代碼請查閱 https://github.com/mcuking/bl...react
接着上一講的中間件機制繼續講。
上一講中咱們實現了redux-thunk中間件,使得加強後的dispatch不只可以接收對象類型的action,還可以接收函數類型的action。
在此咱們是否可以在構造一箇中間件,使得加強後的dispatch還能處理action組成的數組,以下:git
export function buyHouse() { return {type: BUY_House} } export function buyHouseAsync() { return dispatch => { setTimeout(() => { dispatch(buyHouse()) }, 2000) } } export function buyTwice() { return [buyHouse(), buyHouseAsync()] }
爲此咱們決定再構造一箇中間件,命名redux-arrThunk,使加強後的dispatch還能處理action組成的數組。代碼以下:github
const arrThunk = ({dispatch, getState}) => next => action => { // next爲原生的dispatch // 若是是數組,依次執行數組中每個action,參數是dispatch和getState if (Array.isArray(action)) { return action.forEach(v=>dispatch(v)) } // 若是不知足條件,則直接調用下一個中間件(使用next) // 若是知足條件,則須要從新dispatch(調用dispatch) // 默認直接用原生dispatch發出action return next(action) }
由於原理相似第三講中的redux-thunk,上面的代碼並不難,但問題是,咱們如何將這兩個中間件疊加起來使用,爲此咱們須要修改以前的applyMiddleware函數,使其可以接收多箇中間件,而且是的這些中間件可以疊加使用。代碼以下:redux
// applyMiddleware export function applyMiddleware(...middlewares) { return createStore => (...args) => { // 第一步 得到原生store以及原生dispatch const store = createStore(...args) let dispatch = store.dispatch const midApi = { getState: store.getState, dispatch: (...args) => dispatch(...args) } // 第二步 將原生dipatch傳入中間件進行擴展加強,生成新的dispatch const middlewaresChain = middlewares.map(middleware => middleware(midApi)) dispatch = compose(...middlewaresChain)(dispatch) // dispatch = middleware(midApi)(dispatch) return { ...store, // 原生store dispatch, // 加強擴展後的dispatch } } } // compose //compose(fn1, fn2, fn3) return爲 fn1(fn2(fn3)) export function compose(...funcs) { if (funcs.length === 0) { return arg => arg } if (funcs.length === 1) { return funcs[0] } return funcs.reduce((ret, item) => (...args) => ret(item(...args))) }
對比上一講中的applyMiddleware,這一次主要是在處理中間件時,對中間件進行了遍歷,而且經過compose方法使得多箇中間件能夠疊加使用,即將fn1, fn2, fn3 轉換爲 fn1(fn2(fn3))數組
// 以前 dispatch = middleware(midApi)(dispatch) // 以後 const middlewaresChain = middlewares.map(middleware => middleware(midApi)) dispatch = compose(...middlewaresChain)(dispatch)
所以能夠像以下代碼同樣進行疊加使用多箇中間件app
import React from 'react' import ReactDOM from 'react-dom' import { createStore, applyMiddleware } from './mini-redux' import { Provider } from './mini-react-redux' import { counter } from './index.redux' import thunk from './mini-redux-thunk' import arrThunk from './mini-redux-arrThunk' import App from './App' const store = createStore(counter, applyMiddleware(thunk, arrThunk)) ReactDOM.render( ( <Provider store={store}> <App/> </Provider> ), document.getElementById('root') )
其中 const store = createStore(counter, applyMiddleware(thunk, arrThunk))
,意味着加強後的dispatch具備以下功能dom
dispatch(action) = thunk(arrThunk(midApi)(store.dispatch)(action))
至此,咱們的mini-redux就開發完成咯,有任何問題或意見歡迎聯繫我。ide
相關文章以下:函數