redux源码解析之中间件
了解中间件
简略来说,中间件就是对store 的dispatch办法进行包装扩大。
它在 dispatch action 和达到 reducer 的那一刻之间提供了逻辑插入点。能够应用 Redux 中间件进行日志记录、异样监控、与异步 API 对话、路由等。
具体能够见官网文档 Middleware 中间件 | Redux 中武官网
具体实现
在redux中常见的中间件写法为
function middleWare({ getState,dispatch }) { return next => action => { // xxx return next(action) }}
咱们能够看到这里屡次应用到高阶函数,看起来很简单,上面咱们来对他进行逐渐的解析。为了不便标记,我这里将箭头函数,改成函数申明的模式
function middleWare1({ getState, dispatch }) { return function nextHandle1(next) { return function actionHandle1(action) { //xxx return next(action) } }}
上面就开始解说middleware nextHandle actionHandle的具体应用场景
applyMiddleware
首先从入口讲起,常见的应用中间件的形式如下const store = createStore(reducer, applyMiddleware([thunk, logger]));
能够看出,咱们是通过applyMiddleware办法将中间件办法包了一层。那么对应的applyMiddleware办法中解决中间件的流程为:
export default function applyMiddleware( ...middlewares: Middleware[]) {// 省略局部代码 const middlewareAPI: MiddlewareAPI = { getState: store.getState, dispatch: (action, ...args) => dispatch(action, ...args) } // 调用middleware办法,并传参 const chain = middlewares.map(middleware => middleware(middlewareAPI))// 外围逻辑 将函数按序组合 compose(a, b, c)(dispatch) => a(b(c(dispatch))) dispatch = compose<typeof dispatch>(...chain)(store.dispatch) return { ...store, dispatch }}//简化compose函数实现export default function compose(...funcs: Function[]) { return funcs.reduce(function(preFnA, itemFnB){ return function (...args) { return preFnA(itemFnB(...args)); } });}
通过下面两行外围代码middlewares.map以及dispatch = compose(xxx),咱们能够剖析失去middlewares本质上是在对原有的dispatch进行改写增强。
对应的咱们之前写的middleWare1函数在此处被调用,那么就成了
const chain = middlewares.map(middleware => middleware(middlewareAPI))// middlewares在调用map办法后就成了const chain = [nextHandle1, nextHandle2,...]dispatch = compose<typeof dispatch>(...chain)(store.dispatch)// chain中函数再次被compose组合,那么就成了dispatch = actionHandle1(actionHandle2(actionHandle3(store.dispatch)))dispatch = function actionHandle1(action){ console.log('start1') const result = next(action);//此处的next函数即nextHandle2中的actionHandle2 console.log('end1') return result }function actionHandle2(action){ console.log('start2') const result = next(action); //此处的next函数即actionHandle3 console.log('end2') return result }function actionHandle3(action){ console.log('start3') const result = next(action); //此处的next函数即store.dispatch console.log('end3') return result }
实际上在middlewares调用过程中,能够用洋葱模型(面向切面编程(AOP))来形容
上述代码在执行过程中会顺次打印 start1=> start2 =>start3 =>end3=> end2 =>end1。
最两头的那一层就是原始的store.dispatch(action),其余包裹它的中间件,都是对dispatch的增强
总结
到这里,构造就比拟清晰明了了,能够用一个图来概括