在react 或者 react-native開發中,咱們常常使用到以下幾個中間件react
下面這張圖展現了middleware的工做原理,能夠好好的琢磨琢磨,理解這張圖的含義git
爲了理解中間件,讓咱們站在框架做者的角度思考問題:若是要添加功能,你會在哪一個環節添加?github
想來想去,只有在發送 Action 的這個步驟,即store.dispatch()方法,能夠添加功能。舉例來講,要添加日誌功能,把 Action 和 State 打印出來,能夠對store.dispatch進行以下改造。redux
let next = store.dispatch;
store.dispatch = function dispatchAndLog(action) {
console.log('dispatching', action);
next(action);
console.log('next state', store.getState());
}
複製代碼
上面代碼中,對store.dispatch進行了重定義,在發送 Action 先後添加了打印功能。這就是中間件的雛形。react-native
中間件就是一個函數,對store.dispatch方法進行了改造,在發出 Action 和執行 Reducer 這兩步之間,添加了其餘功能。數組
本教程不涉及如何編寫中間件,由於經常使用的中間件都有現成的,只要引用別人寫好的模塊便可。好比,上一節的日誌中間件,就有現成的redux-logger模塊。這裏只介紹怎麼使用中間件。promise
import { applyMiddleware, createStore } from 'redux';
import createLogger from 'redux-logger';
const logger = createLogger();
const store = createStore(
reducer,
applyMiddleware(logger)
);
複製代碼
上面代碼中,redux-logger提供一個生成器createLogger,能夠生成日誌中間件logger。而後,將它放在applyMiddleware方法之中,傳入createStore方法,就完成了store.dispatch()的功能加強。bash
這裏有兩點須要注意:app
const store = createStore(
reducer,
initial_state,
applyMiddleware(logger)
);
複製代碼
const store = createStore(
reducer,
applyMiddleware(thunk, promise, logger)
);
複製代碼
上面代碼中,applyMiddleware方法的三個參數,就是三個中間件。有的中間件有次序要求,使用前要查一下文檔。好比,logger就必定要放在最後,不然輸出結果會不正確。框架
看到這裏,你可能會問,applyMiddlewares這個方法究竟是幹什麼的?
它是 Redux 的原生方法,做用是將全部中間件組成一個數組,依次執行。下面是它的源碼。
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var store = createStore(reducer, preloadedState, enhancer);
var dispatch = store.dispatch;
var chain = [];
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
};
chain = middlewares.map(middleware => middleware(middlewareAPI));
dispatch = compose(...chain)(store.dispatch);
return {...store, dispatch}
}
}
複製代碼
上面代碼中,全部中間件被放進了一個數組chain,而後嵌套執行,最後執行store.dispatch。能夠看到,中間件內部(middlewareAPI)能夠拿到getState和dispatch這兩個方法。
在Redux框架下使用中間件的主要好處就是:方便在action中接收dispatch和getState兩個參數,也就是咱們不須要在觸發action時候傳遞這兩個參數,咱們就能獲取到。主要是由於react-thunk會在異步處理中默認傳過來,以便於咱們在action中進一步dispatch其餘的操做。
其實本身寫一箇中間件也是簡單的,下面就是自定義的thunkMiddleware
/**
* Created by guangqiang on 2017/8/29.
*/
export default thunkMiddleware = extraArgument => {
return ({getState, dispatch}) => next => action => {
if (typeof action === 'function') {
return action(getState, dispatch, extraArgument)
}
return next(action)
}
}
複製代碼