若是你用過express.js之類的web框架,對中間件(Middleware)這個概念可能不會陌生。中間件其實就是一種獨立運行於各個框架組件之間的膠水代碼。在Express.js或Koa等框架中,中間件一般是運行在收到請求處處理請求之間,但是實現日誌記錄、身份認證等預處理操做。而在Redux裏,中間件是運行在action發送出去,到達reducer之間的一段代碼。html
編寫中間件日誌記錄是開發過程當中經常使用的一個功能,你能夠選擇侵入業務邏輯來記錄日誌(不推薦),也能夠選擇使用中間件來實現這個功能。接下來讓咱們編寫一個經常使用的日誌記錄中間件:web
const loggerMiddleware = store => next => action => { console.group(action.type); console.log('action: ', action); const result = next(action); console.log('next state: ', store.getState()); console.groupEnd(action.type); return result; }
使用中間件的時候,要在初始化store的時候利用applyMiddleware
注入進去:express
const store = createStore( rootReducer, applyMiddleware(loggerMiddleware) )
這樣,咱們在每次觸發action的時候就能記錄咱們所須要的信息。一樣的方式,也能夠實現日誌上報等功能。編程
組合中間件中間件實際上是一種高層次的抽象,能夠將核心領域業務和基礎架構邏輯解耦開來。而多箇中間件能夠組合使用,從而使每個中間件可以保持「小而美」的特性。架構
const store = createStore( rootReducer, applyMiddleware(thunk, loggerMiddleware) )
其中applyMiddleware
函數能夠接收多箇中間件,源碼以下:app
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 } } } export default function compose(...funcs) { if (funcs.length === 0) { return arg => arg } if (funcs.length === 1) { return funcs[0] } const last = funcs[funcs.length - 1] const rest = funcs.slice(0, -1) return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args)) }
咱們能夠看到它主要作了幾個工做:框架
store.getState
,dispatch
傳入每一箇中間件中,並收集調用鏈結果。以後在應用中全部使用的dispatch都將是修改過的邏輯,從中咱們能夠看出有點面向切面編程
的味道,能夠好好體會一下。ide