再学习redux的过程当中,Middleware这块感受很烧脑,因此对它的原理进行整理redux
有一些比较基础的先不整理,数组
以日志中间件为例闭包
//如下的这种写法属于柯里化的知识 const logger = state => next => action =>{ console.log('dispatch', action); next(action); console.log('nextState',store.getState); }
以上的代码能够解释成app
var logger = function logger(state) { return function (next) { return function (action) { console.log('dispatch', action); next(action); console.log('nextState', store.getState); }; }; };
//applyMiddleware 源码 export default function applyMiddleware(...middlewares) { //假如说 middlewares 里有三个mid1,mid2,mid3 return (createStore) => (reducer, preloadedState, enhancer) => { const store = createStore(reducer, preloadedState, enhancer) let dispatch = store.dispatch let chain = [] //一个保存了store状态,和dispatch方法的对象 这个对应的就是logger 的store const middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action)//经过闭包的形式引用外部的dispatch } //执行了middleware方法,返回了须要next参数的方法 的数组 chain = middlewares.map(middleware => middleware(middlewareAPI)) //假如chain 为[f1,f2,f3,f4,f5,f6,f7] //那么下面这句话的翻译就是这样 dispatch = f1(f2(f3(f4(f5(f6(f7(store.dispatch))))))) //就是将chain中的函数串联到一块儿,这种组合从最里面开始执行,返回的结果做为上一个函数的参数,一直向外执行 //就是至关于从chain函数的最右侧到最左侧执行 //compose(...chain) 返回的是一个匿名函数 function compose(...funcs) funcs就是chain //return funcs.reduce((a, b) => (...args) => a(b(...args))) 这里的args就是store.dispatch dispatch = compose(...chain)(store.dispatch) //dispatch = f1(f2(f3(f4(f5(f6(f7(store.dispatch))))))) //当调用dispatch的时候就依次执行 return { ...store, dispatch// 这个是处理过的dispatch } } }
chain = middlewares.map(middleware => middleware(middlewareAPI))
这里能够看出来,在日志中间件中的第一层的store就是middlewareAPI
而且将第二层返回到chain的数组中
这就至关于当初的store => next => action =>{...}变成了next => action =>{...}函数
dispatch = compose(...chain)(store.dispatch) function compose(...funcs) { if (funcs.length === 0) { return arg => arg } if (funcs.length === 1) { return funcs[0] } return funcs.reduce((a, b) => (...args) => a(b(...args))) }
这一步至关于把chain数组中函数,经过处理获得一种相似于层层嵌套的结构f1(f2(f3(f4(args))))
因此dispatch = A(B(C(store.dispatch))学习
单个中间件较为简单,因此拿三个中间件作例子
经上面所述spa
//由于抛开store,剩下的中间件的结构相似于下面这种 function A1(next){ return function A2(action){ next(action) } } function B1(next){ return function B2(action){ next(action) } } function C1(next){ return function C2(action){ next(action) } }
//dispatch = A(B(C(store.dispatch)) //这种结构会先执行最内部的函数,也就是C(store.dispatch)这一块 //当执行了C 返回的是一个函数 function C2(action){ store.dispatch(action) } //返回值最为他的外层函数的参数next next = function C2(action){ store.dispatch(action) } //此时的结构相似于这种 dispatch = A(B(function C2(action) { store.dispatch(action) }(action) ) ) //接下来执行B,返回了 next = function C2(action){ function C2(action){ store.dispatch(action) }(action) } //此时的结构相似于这种 dispatch = A(function B2(action) { function C2(action){ store.dispatch(action) }(action) }(action) ) //接下来执行A,返回了 dispatch = function A2(action){ function B2(action) { function C2(action){ store.dispatch(action) }(action) }(action) }(action)
最后返回新的store翻译
总结日志