Redux-Middleware-原理解析

再学习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翻译


总结日志

  1. 调用applyMiddleware 传入n个中间件的数组
  2. 用一个middlewareAPI保存当前的store.getState,和dispatch所指向的函数
  3. 迭代中间件数组,并执行一遍,将middlewareAPI做为最外层的store,而且返回一个至关于next函数的数组
  4. 将数组整理成嵌套的函数体,并将store.dispatch传入最内侧的函数的next,并返回通过处理的dispatch (dispatch是一个通过处理的函数,是一个嵌套了多层的函数,其最里面调用的是store.dispatch)
  5. 返回一个新的store
相关文章
相关标签/搜索