Last Surprise Lyn
  1. 1 Last Surprise Lyn
  2. 2 Warcry mpi
  3. 3 The Night We Stood Lyn
  4. 4 Life Will Change Lyn
  5. 5 Quiet Storm Lyn
  6. 6 One Last You Jen Bird
  7. 7 かかってこいよ NakamuraEmi
  8. 8 Flower Of Life 发热巫女
  9. 9 Hypocrite Nush
  10. 10 Libertus Chen-U
  11. 11 Time Bomb Veela
2018-01-24 21:31:47

Redux中间件和store enhancer分析

Redux的中间件思想和Koa很相似,Redux的action对象可以类比于Koa中的客户端请求,所有的中间件就组成了处理action对象的管道,最后将处理完成的action对象交给reducer就完成了中间件流程。


applyMiddleware

Redux提供了applyMiddleware方法作为加载中间件的入口,源码如下:

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
    }
  }
}

可以看到,该方法的作用是拓展createStore,增强其创建的store的dispatch功能,这也是中间件的作用原理:通过中间件的数组chain改变原始dispatch的内容来达到拓展action对象的目的。

得到数组chain需要对中间件数组传入通用的中间件API并调用中间件函数得到,那么来看一下中间件的通用结构:

const middleware = store => next => action => {
  // 传递到下一个中间件前执行的代码
  // ...
  let result = next(action)
  // 传递后执行的代码
  // ...
  return result
}

可以看到数组chain内存放的都是一个接受参数为next的函数,该参数实际上就是store.dispatch,会在action对象处理完后执行,作用在于将处理过的action对象传递到下一个中间件。传递逻辑实现的关键就是处理数组chain的compose函数。


compose

这个函数就是中间件实现的精华所在了,实际上就是函数式编程中的组合。它将chain中的所有函数组合成一个新的函数并生成一个新的dispatch。源码如下:

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))
}

简单理解就是一行代码:

compose(f1, f2, f3)(arg) = f1(f2(f3(arg)));

将数组chain从右到左传原始的store.dispatch执行,每一个中间件数组元素执行后生成包装过的dispatch继续传入下下一个中间件数组元素,reduce完成后即返回最新的result作为最终增强的dispatch。

再回头看一下中间件的通用结构来梳理整套流程。

const middleware = store => next => action => {
  // 传递到下一个中间件前执行的代码
  // ...
  let result = next(action)
  // 传递后执行的代码
  // ...
  return result
}
// 1.接受middlewareAPI作为参数store生成数组chain中的函数,每个函数接受dispatch作为next参数
// 2.从原始dispatch开始从右往左reduce增强,返回的接受action参数的函数即为新的dispatch,最终取代store的dispatch

store enhancer

现在明白了中间件的原理,进一步的就需要理解store enhancer的概念了。前面已经提到了中间件的入口是applyMiddleware函数,实际上这就是一个store enhancer,正如其名,其增强了store的dispatch功能。回头再想想我们是怎么使用applyMiddleware的?

const storeEnhancers = compose(
    applyMiddleware(...middlewares),
    ...
)
const store = createStore(reducer, initialState, storeEnhancers);

createStore接受的第3个参数即为store enhancer,一个store enhancer实际上就是一个高阶函数,参数为创建store的函数,返回值可以创建增强型的创建store的函数用来取代初始createStore,这里的思想和中间件内部增强dispatch的思想一致,同样通过compose合成enhancer数组来获取最终的createStore。

-- EOF --

添加在分类「 前端开发 」下,并被添加 「React」 标签。