Redux中间件原理解析

97 阅读2分钟

我在这里梳理下redux中间件的原理,首先说两个概念,store enhancer 与 dispatch enhancer。createStore(reducer, initState, enhancer)第三个参数就是store enhancer 是用来增加store的,除了可以扩展dispatch还可以扩展其他东西,我们平时用的midddleware则是dispatch enhancer。

store enhancer 函数签名为:(createStore) =>( reducer, preloadedState) => store

middeware 函数签名:({getState,dispatch}) => next => action => next(action)或其他

我们平时使用的window.__REDUX_DEVTOOLS_EXTENSION和applyMiddleware都属于store enhancer creater, 执行之后生成 store enhancer

源码解析:

export default function applyMiddleware(...middlewares) {
  return (createStore) =>( reducer, preloadedState) => {
    const store = createStore(reducer, preloadedState)
    let dispatch = () => {
      throw new Error(
        'Dispatching while constructing your middleware is not allowed. ' +
          'Other middleware would not be applied to this dispatch.'
      )
    }

    const middlewareAPI = {
      getState: store.getState,
      dispatch: (action, ...args) => dispatch(action, ...args)
    }
    // 第一步(执行第一层): 传入统一的getState、dispatch
    const chain = middlewares.map(middleware => middleware(middlewareAPI))
    // 第二步(compose组合): 生成  (...args) => mid1(mid2(args))
    // 第三步(执行)
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}
// 这里我们举个例子有两个中间件:1 >> 3 代表了中间件的三层结构
// middleware的签名:({getState,dispatch}) => next => action => f
function mid1_1 ({ dispatch, getState }) {
    return function mid1_2 (next) {
        return function mid1_3 (action) {
            console.log('当前action1: ', action)
            next(action)
            console.log('更改之后的store1:', dispatch, getState())
        }
    }
}
function mid2_1 ({ dispatch, getState }) {
    return function mid2_2 (next) {
        return function mid2_3 (action) {
            console.log('当前action2: ', action)
            next(action)
            console.log('更改之后的store2:', dispatch, getState())
        }
    }
}
// 在使用applymiddleware 的过程中,我们只关注三个关键步骤:

// 第一步:const chain = middlewares.map(middleware => middleware(middlewareAPI)),每个中间件得到了同样的getState 和 dispatch(暂时为假的,防止在创建过程中调用dispatch),得到如下结果
chain = [mid1_2, mid2_2]

// 第二步:compose 将上面的中间件数组组合成一个大函数,mid2-2的结果,做为mid1_2的 next参数,下一步会传入真正的dispatch,则最后一个中间件的next 为dispatch,其他中间件的next则为后面中间件的返回结果
function (...args) {
  return mide1_2( mid2_2(args) )
}

// 第三步:执行上面得到的函数,传入真正的dispatch得到最终的dispatch函数
function mid1_3 (action) {
    console.log('当前action1: ', action)
    mid2_3(action)
    console.log('更改之后的store1:', getState())
}

// 此时mid1_3 与 mid2_3 的内部
mid1_3 中:
dispatch: 改造之后的dispatch(dispatch = compose(...chain)(store.dispatch),改变了之前的dispatch)
getState: 原生的store.getState
next: 变为mid2_3函数
mid2_3中:
dispatch: 改造之后的dispatch
getState: 原生的store.getState
next: store.dispatch