在研究 redux-saga
時,發現本身對 redux middleware
不是太瞭解,所以,便決定先深刻解讀一下 redux
源碼。跟大多數人同樣,發現 redux源碼 真的很精簡,目錄結構以下:javascript
|—— utils |—— warnings.js |—— applyMiddleware.js |—— bindActionCreator.js |—— combineReducers.js |—— compose.js |—— createStore.js |—— index.js
在 index.js
中導出了5個模塊,即外部可用的:html
export { createStore, combineReducers, bindActionCreators, applyMiddleware, compose }
然而,當真正解讀的時候,發現還真是有點吃不消,通過幾天的硬啃以後,只能說:終於等到你,還好我沒放棄。。。(自帶BGM)java
這裏,我可能不會仔細去分析它的源碼,但會就本身的理解進行梳理歸納,具體的對我頗有幫助的文章會放到結尾參考處。react
首先是對 createStore
、 applyMiddleware
及 compose
的梳理,由於這3個模塊存在相互調用的關係,其關係圖以下(高清圖請查看 redux源碼圖解之createStore和applyMiddleware):git
createStore
的函數的做用就是生成一個 store 對象,這個對象具備5個方法:github
return { dispatch, // 傳入 action,調用 reducer 及觸發 subscribe 綁定的監聽函數 subscribe, getState, replaceReducer, // 用新的 reducer 代替當前的 reducer,使用很少 [$$observable]: observable }
而 applyMiddleware
函數的做用就是對 store.dispatch
方法進行加強和改造,使得在發出 Action 和執行 Reducer 之間添加其餘功能。redux
compose
函數則是 applyMiddleware
函數的核心,其會造成串聯的函數調用關係,用於加強 dispatch
方法。數組
(i) 首先,createStore
模塊會對傳入的參數進行判斷,分別處理不一樣參數的狀況,當傳入 applyMiddleware(...middleware)
的時候,就會返回 applyMiddleware(...middleware)
執行以後的高階函數,即:架構
// createStore.js if (typeof enhancer !== 'undefined') { if (typeof enhancer !== 'function') { throw new Error('Expected the enhancer to be a function.') } // 這裏的 enhancer 是 applyMiddleware(...) 執行後的高階函數,傳參無 enhancer return enhancer(createStore)(reducer, preloadedState) }
(ii)而後,就進入了 applyMiddleware
模塊內部的邏輯,從 createStore
返回的高階函數,其傳入的參數是沒有 enhancer
的,所以走的是 createStore
函數中沒有傳入 enhancer 的邏輯,用於先得到沒有中間件時返回的 store。app
// applyMiddleware.js export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { const store = createStore(reducer, preloadedState, enhancer) let dispatch = store.dispatch let chain = [] // 用於存放獲取了store的中間件數組 const middlewareAPI = { getState: store.getState, dispatch: (...args) => dispatch(...args) } chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) return { ...store, dispatch } } }
(iii)接着,獲取最原始的 store 的 getState
和 dispatch
,封裝於 middlewareAPI
對象。將該對象傳入中間件 middleware
中,造成中間件數組 chain
。
其中,middleware
的範式是:(store) => (next) => (action) => {}
,將 middlewareAPI
傳入middleware
後,中間件便得到了 {getState, dispacth}
。至此,chain 中間件數組中包含的每一箇中間件的形式都變成了 (next) => (action) => {}
的形式。
(iiii)最後,調用 compose
函數,如 chian = [middleware1, middleware2, middleware3]
,則 dispatch = compose(...chain)(store.dispatch)
,即執行 middleware1(middleware2(middleware3(store.dispatch)))
,而後賦值給 dispatch
。
總之,無論是否有
applyMiddleware
,createStore
的結果都是輸出一個 store 對象,而applyMiddleware
則能夠對 store 對象中的dispatch
進行改造。