若是你用过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