歡迎關注redux源碼分析系列文章:
redux源碼分析之一:createStore.js
redux源碼分析之二:combineReducers.js
redux源碼分析之三:bindActionCreators.js
redux源碼分析之四:compose.js
redux源碼分析之五:applyMiddlewareredux
redux中間件其實很是簡單,中間件的目的只有一個:在dispatch先後,執行一些代碼,達到加強dispatch的效果,有點相似裝飾器的原理。segmentfault
applyMiddleware須要結合createStore函數來看,appleyMiddleware就是createStore的第三個參數enhancer,好比,對redux-logger中間件,其使用方式以下:api
import { applyMiddleware, createStore } from 'redux'; import { createLogger } from 'redux-logger'; const logger = createLogger(); const store = createStore( reducer, applyMiddleware(logger) )
applyMiddleware文件的源碼以下:app
export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { const store = createStore(reducer, preloadedState, enhancer) let dispatch = store.dispatch let chain = [] const middlewareAPI = { getState: store.getState, dispatch: (...args) => dispatch(...args) } chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) return { ...store, dispatch } } }
函數的返回值自己,也是另一個函數,而這個函數,接受的參數是createStore,結合createStore的前幾行源碼來看:函數
export default function createStore(reducer, preloadedState, enhancer) { if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') { enhancer = preloadedState preloadedState = undefined } if (typeof enhancer !== 'undefined') { if (typeof enhancer !== 'function') { throw new Error('Expected the enhancer to be a function.') } return enhancer(createStore)(reducer, preloadedState) } //其他代碼這裏忽略 }
能夠看到,createStore的第三個參數ehancer若是是一個函數的話,就會優先執行ehancer,而後再再enhancer內部調用createStore函數,因此,createStore其實只會執行一些,也只會生成一個store。源碼分析
我添加了代碼註釋以下:(關於compose函數的解釋,請參考文章:redux源碼分析之四:compose.js):spa
export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { //這裏會原封不動的執行createStore,並根據入參生成一個store const store = createStore(reducer, preloadedState, enhancer) //把dispatch從store中取出來 let dispatch = store.dispatch let chain = [] //這裏約定了全部的redux中間件只能使用的api就是2個,getState和dispatch const middlewareAPI = { getState: store.getState, dispatch: (...args) => dispatch(...args) } 對每個中間件,執行中間件函數,並將中間件api對象傳入函數,用chain變量接收中間件執行結果的其返回值 chain = middlewares.map(middleware => middleware(middlewareAPI)) //這裏用到了compose函數,分別按順序從後往前執行每個中間件,而且前一箇中間件的返回值做爲後一箇中間件的入參,全部中間件的第一個入參是原始的store.dispatch dispatch = compose(...chain)(store.dispatch) //最後返回store對象,只是,使用了通過中間件加工過的dispatch對象,替換掉原始的dispatch對象 return { ...store, dispatch } } }
redux中間件只有一個目的:在dispatch先後,執行一些代碼,達到加強dispatch的效果,有點相似裝飾器的原理。,理解好了這一點就ok了。
下一篇文章會給你們帶來一個最簡單的redux中間件,敬請期待。code