在建立store時,createStore(reducer, preloadedState, enhancer)
,除了reducer函數,初始狀態,還能夠傳入enhancer
。這個enhancer在createStore的源碼中是這樣使用的redux
return enhancer(createStore)(reducer, preloadedState)
它能夠接受createStore方法並進行自定義改裝,而後再使用改裝後的方法建立倉庫。app
而redux官方提供的enhancer就只有applyMiddleware
。函數
applyMiddleware的主要功能是改寫createStore中的dispatch
方法,而且能夠將多個middleware組合到一塊兒,形式鏈式的調用,先後互不影響。這樣要求middleware必須遵循必定的格式。({ getState, dispatch }) => next => action => {}
this
export default function applyMiddleware(...middlewares) { // 返回一個enhancer函數,接受createStore做爲參數(能夠對照enhancer的調用方式來看) return createStore => (...args) => { // enhancer函數接受reducer, preloadedState來建立倉庫 const store = createStore(...args) // 自定義dispatch函數,在構造middleware的時候,不容許調用dispatch let dispatch = () => { throw new Error( `Dispatching while constructing your middleware is not allowed. ` + `Other middleware would not be applied to this dispatch.` ) } const middlewareAPI = { getState: store.getState, // store中的getState函數,用於獲取狀態 dispatch: (...args) => dispatch(...args) // 自定義的dispatch函數 } // 傳入到getState,和dispatch到middleware中 生成 next => action => {} 格式的函數 const chain = middlewares.map(middleware => middleware(middlewareAPI)) // 自定義的dispatch更新爲 多個middleware的組合函數;傳入store本來dispatch函數給組合函數(會在最後一個middle中做爲next函數) dispatch = compose(...chain)(store.dispatch) // 返回store倉庫,此時的dispatch函數已被改寫,爲多個middleware的組合函數 return { ...store, dispatch } } }
關鍵是要理解這裏dispatch = compose(...chain)(store.dispatch)
,dispatch被改寫爲多個middleware的組合函數。spa
compose函數中關鍵的一句是return funcs.reduce((a, b) => (...args) => a(b(...args)))
code
a能夠理解爲next => action => {}
,而next
能夠理解爲b(...args)
就是下一個middleware的 ation => {}
函數。因此實現了鏈式調用。a中作了自定義的操做,會調用b,b調用c···最後一個調用store.dispatch
。blog
用兩個middleware作例子來梳理改寫後的dispatch(action)
的調用過程。get
middleware必須遵循必定的格式。({ getState, dispatch }) => next => action => {}
源碼
{getState, dispatch}參數是在applyMiddleware的源碼中const chain = middlewares.map(middleware => middleware(middlewareAPI))
這一部分被傳入的,store的getState和改寫後的dispatch。io
next是下一個middleware或者store.dispatch,action是觸發的動做
/*logger*/ export default ({dispatch,getState}) => next => action => { // 作一些自定義的事情 console.log('will dispatch ation',action); console.log('next in loggere',next); // 調用下一個middleware let returnValue = next(action); console.log('state after dispatch',getState()); return returnValue; }
/*test*/ export default ({dispatch,getState}) => next => action => { console.log('next in test',next) return next(action); }
store = createStore(reducer,applyMiddleware(logger,test))
觸發action時,有以下打印
logger作完自定義操做後,調用下一個middleware(test)函數,test是最後一個middleware,它的next是store.dispatch,就觸發了action。