什麼是中間件
在redux中,我們可以在view層dispatch一個action,action到達store中的reducer,reducer根據action的type更新處理state,從而更新store中的數據。但是redux並不能處理異步的dispatch。這時候我們就需要使用redux提供的applyMiddleware對dispatch進行增強,使我們的dispatch可以異步。
這裏重點討論applyMiddleware這個中間層,是如何工作的。
中間件的使用
const store = createStore(myReducer, applyMiddleware(logger, thunk));
分析下源碼,createStore是如何使用這個applyMiddleware的勒?看看下面這段源碼yourProject\node_modules\[email protected]@redux\lib\redux.js
,applyMiddleware(logger, thunk)
執行的結果就是enhancer,作爲一個增強器去包裝處理reducer。
function createStore(reducer, preloadedState, enhancer) {
···
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
enhancer = preloadedState;
preloadedState = undefined;
}
···
return enhancer(createStore)(reducer, preloadedState); // 關鍵代碼
}
那咱們接下來看看applyMiddleware(logger, thunk)
執行的結果enhancer是個什麼呢?
中間件applyMiddleware做了什麼
源碼地址也是在這裏哦,yourProject\node_modules\[email protected]@redux\lib\redux.js
。
// 中間件
function applyMiddleware() {
// 將fn參數收集到middlewares,這是一個fn數組
for (var _len = arguments.length, middlewares = new Array(_len), _key = 0; _key < _len; _key++) {
middlewares[_key] = arguments[_key];
}
// 返回一個函數,enhancer,看看enhancer的調用,enhancer(createStore)(reducer, preloadedState);
return function (createStore) {
// 又返回一個函數,此時參數爲(reducer, preloadedState)
return function () {
// 利用初始reducer,創建store,這個store和咱們沒有用中間件的時候一樣哦~
var store = createStore.apply(void 0, arguments);
var _dispatch = function dispatch() {
throw new Error('Dispatching while constructing your middleware is not allowed. ' + 'Other middleware would not be applied to this dispatch.');
};
// 對store進行了簡單的包裝,用於攔截增強函數中的dispatch
var middlewareAPI = {
getState: store.getState,
dispatch: function dispatch() {
return _dispatch.apply(void 0, arguments);
}
};
// 關鍵代碼,遍歷fn數組,將middlewareAPI(包裝過的store)作爲參數傳遞進去執行該函數
var chain = middlewares.map(function (middleware) {
return middleware(middlewareAPI);
});
// compose是一個基於reduce的方法,將fn數組進行套娃[fn1, fn2, fn3] => fn1(fn2(fn3(arguments)))
// fn1(fn2(fn3(arguments)))的實參是真實原始的dispatch,真正意義上的對原始dispatch做增強
_dispatch = compose.apply(void 0, chain)(store.dispatch);
// 返回store,此時store擁有superDispatch啦!
return _objectSpread2({}, store, {
dispatch: _dispatch
});
};
};
}
// 組裝器
function compose() {
···
return funcs.reduce(function (a, b) {
return function () {
return a(b.apply(void 0, arguments));
};
});
}