再學習redux的過程當中,Middleware這塊感受很燒腦,因此對它的原理進行整理redux
有一些比較基礎的先不整理,數組
以日誌中間件爲例閉包
//如下的這種寫法屬於柯里化的知識 const logger = state => next => action =>{ console.log('dispatch', action); next(action); console.log('nextState',store.getState); }
以上的代碼能夠解釋成app
var logger = function logger(state) { return function (next) { return function (action) { console.log('dispatch', action); next(action); console.log('nextState', store.getState); }; }; };
//applyMiddleware 源碼 export default function applyMiddleware(...middlewares) { //假如說 middlewares 裏有三個mid1,mid2,mid3 return (createStore) => (reducer, preloadedState, enhancer) => { const store = createStore(reducer, preloadedState, enhancer) let dispatch = store.dispatch let chain = [] //一個保存了store狀態,和dispatch方法的對象 這個對應的就是logger 的store const middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action)//經過閉包的形式引用外部的dispatch } //執行了middleware方法,返回了須要next參數的方法 的數組 chain = middlewares.map(middleware => middleware(middlewareAPI)) //假如chain 爲[f1,f2,f3,f4,f5,f6,f7] //那麼下面這句話的翻譯就是這樣 dispatch = f1(f2(f3(f4(f5(f6(f7(store.dispatch))))))) //就是將chain中的函數串聯到一塊兒,這種組合從最裏面開始執行,返回的結果做爲上一個函數的參數,一直向外執行 //就是至關於從chain函數的最右側到最左側執行 //compose(...chain) 返回的是一個匿名函數 function compose(...funcs) funcs就是chain //return funcs.reduce((a, b) => (...args) => a(b(...args))) 這裏的args就是store.dispatch dispatch = compose(...chain)(store.dispatch) //dispatch = f1(f2(f3(f4(f5(f6(f7(store.dispatch))))))) //當調用dispatch的時候就依次執行 return { ...store, dispatch// 這個是處理過的dispatch } } }
chain = middlewares.map(middleware => middleware(middlewareAPI))
這裏能夠看出來,在日誌中間件中的第一層的store就是middlewareAPI
而且將第二層返回到chain的數組中
這就至關於當初的store => next => action =>{...}變成了next => action =>{...}函數
dispatch = compose(...chain)(store.dispatch) function compose(...funcs) { if (funcs.length === 0) { return arg => arg } if (funcs.length === 1) { return funcs[0] } return funcs.reduce((a, b) => (...args) => a(b(...args))) }
這一步至關於把chain數組中函數,經過處理獲得一種相似於層層嵌套的結構f1(f2(f3(f4(args))))
因此dispatch = A(B(C(store.dispatch))學習
單箇中間件較爲簡單,因此拿三個中間件作例子
經上面所述spa
//由於拋開store,剩下的中間件的結構相似於下面這種 function A1(next){ return function A2(action){ next(action) } } function B1(next){ return function B2(action){ next(action) } } function C1(next){ return function C2(action){ next(action) } }
//dispatch = A(B(C(store.dispatch)) //這種結構會先執行最內部的函數,也就是C(store.dispatch)這一塊 //當執行了C 返回的是一個函數 function C2(action){ store.dispatch(action) } //返回值最爲他的外層函數的參數next next = function C2(action){ store.dispatch(action) } //此時的結構相似於這種 dispatch = A(B(function C2(action) { store.dispatch(action) }(action) ) ) //接下來執行B,返回了 next = function C2(action){ function C2(action){ store.dispatch(action) }(action) } //此時的結構相似於這種 dispatch = A(function B2(action) { function C2(action){ store.dispatch(action) }(action) }(action) ) //接下來執行A,返回了 dispatch = function A2(action){ function B2(action) { function C2(action){ store.dispatch(action) }(action) }(action) }(action)
最後返回新的store翻譯
總結日誌