在建立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。