hello,大家好,之前我們大概分析了一下createStore中的代碼,但應該還是有很多迷迷糊糊的,感覺不知所以。畢竟這個redux中有很多的牽扯,所以當你把整個redux源碼都看了一遍,就會大概的瞭解redux的原理 下面我們來分析一下applyMiddleware export default function applyMiddleware(...middlewares) { // 傳入中間件的數組 return (createStore) => (reducer, preloadedState, enhancer) => { 返回一個函數 const store = createStore(reducer, preloadedState, enhancer) // 創建store let dispatch = store.dispatch // 獲得store的dispatch let chain = [] // 聲明空數組 用來存儲action增強函數 const middlewareAPI = { // getState: store.getState, // 通過store獲取state dispatch: (action) => dispatch(action) // dispatch方法 } // 傳進來的middlewares 進行遍歷 返回新數組 chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) // 使用compose進行柯里化 // 在使用了middleWare的情況下,這裏就是我們createStore的返回值。 return { ...store, dispatch } }
大體代碼是做什麼的已經用註釋講解了,但是可能大家還是有一點朦朦的。
例如爲什麼applyMiddleware這個函數 又返回了一個多重箭頭函數, 爲什麼disaptch這樣就能增強action
這個就會牽扯到我們上一篇講的createStore
const enhancer = compose( applyMiddleware(...middlewares) );
const store = createStore( combineReducers({ ...reducers }), initialState, enhancer );
這裏的enhancer 等價於 applyMiddleware(...middlewares)
在createStore中傳入enhancer 和 applyMiddleware(...middlewares)效果是一樣的。
所以相當於applyMiddleware(...middlewares)這個就是createStore傳入的 enhancer,在createStore中enhancer要求是一個函數,
現在我們看看applyMiddleware(...middlewares)的返回結果,這裏返回了一個函數。
if (typeof enhancer !== 'undefined') { if (typeof enhancer !== 'function') { throw new Error('Expected the enhancer to be a function.') } return enhancer(createStore)(reducer, preloadedState) }
從上面的代碼我們可以看到我們首先將createStore傳入 applyMiddleware(...middlewares)返回的函數中,然後在將state和reducer傳入到enhancer(createStore)返回的函數中。
這樣我們就可以知道在我們傳入中間件的情況下
const store = createStore(reducer, preloadedState, enhancer) // 創建store
這一行代碼纔是創建store執行者。
然後我們通過創建的store或者state 和 dispatch 然後創建了一個middlewareAPI 並將其傳入middleware中,
這是爲了讓中間件可以直接和store來進行溝通。
接下來的兩行代碼可以說是applyMiddleware中最核心的代碼了
chain = middlewares.map(middleware => middleware(middlewareAPI))
首先通過map將其遍歷 執行中間件。
我們用一下redux-thunk的源碼來進行對應的講解
redux-thunk源碼:
function createThunkMiddleware(extraArgument) { return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; } const thunk = createThunkMiddleware(); thunk.withExtraArgument = createThunkMiddleware; export default thunk;
這裏獲得的thunk 是createThunkMiddleware的執行結果 thunk相當於
({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); };
當我們只有middleWare中只有一個thunk的時候
這時候我們applyMiddleware中的 middlerwares = [ thunk ]
chain = middlewares.map(middleware => middleware(middlewareAPI))
就相當於 chain = middlewares.map(thunk = thunk(middlewareAPI));
執行結果: chain = [ thunk() ]
關於thunk多重箭頭函數中的next 和 action 是從哪裏來的呢?
具體是由於下面這一句代碼的執行,所引起的
dispatch = compose(...chain)(store.dispatch)
export default 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))) }
以上是compose的源碼
我們看一下里面最核心的就是最後一句代碼
return funcs.reduce((a, b) => (...args) => a(b(...args)))
這裏使用了reduce操作,我們假設傳進去的數組裏面有3箇中間件A,B,C,然這執行後返回的結果爲(..args)=>A(B(C(...args))) 這樣一個函數。
然後我們在看看dispatch = compose(...chain)(store.dispatch) 這一行,我們將store.dispatch 傳遞了進去,所以我們 上面的
(..args)=>A(B(C(...args))) => (store.dispatch) => A(B(C(store.dispatch)));
我們這時候可以看看thunk中間件代碼,然後結合上面推出來的表達式,我們能看到如果是最後一箇中間件,那麼他的next是store.dispatch,如果不是最後一個,那麼他的next就是 後一個函數的執行結構。
我們可以推斷出來 (store.dispatch) => A(B(C(store.dispatch))) 這一行的返回結果是
以thunk代碼爲例: 我們執行後會返回這樣一個箭頭函數。 我們下文將這個箭頭函數簡稱爲Action函數
action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); };
所以不管有多少箇中間件我 compose(...chain)(store.dispatch) 這裏返回的一定是Action函數,
然後把這個賦值給dispatch,這個dispatch就是我們正常使用的dispatch函數。
我們在使用redux的時候會調用dispatch這個方法 eg: disptach(action) ;
在我們調用的時候我們將action傳遞進去,然後傳遞到 compose(...chain)(store.dispatch) 返回的函數,執行函數體,然後我們最後返回next(action) 這裏的next指向下一個中間件的 Action函數,直到最後面指向store.dispatch;
現在基本解釋完了,我們接下來看源碼 最後返回了一個對象裏面返回了創建的store對象,和增強後的dispatch方法。