理解applyMiddleware和createStore之间的关系

前言

不得不佩服redux的作者Dan Abramov,看完applyMiddleware的源码,我的感受就是:还有这种操作?
与其说是理解applyMiddleware,不如说是理清createStoreapplyMiddleware和一些中间件的关系,和为什么中间件都是export const createThunkMiddleware = ({ dispatch, getState }) => next => action => {...}三层嵌套关系。

export default function applyMiddleware() {
  for (var _len = arguments.length, middlewares = Array(_len), _key = 0; _key < _len; _key++) {
    middlewares[_key] = arguments[_key];
  }

  return function (createStore) {
    return function (reducer, preloadedState, enhancer) {
      var store = createStore(reducer, preloadedState, enhancer);
      var _dispatch = store.dispatch;
      var chain = [];

      var middlewareAPI = {
        getState: store.getState,
        dispatch: function dispatch(action) {
          return _dispatch(action);
        }
      };
      chain = middlewares.map(function (middleware) {
        return middleware(middlewareAPI);
      });
      _dispatch = compose.apply(undefined, chain)(store.dispatch);

      return _extends({}, store, {
        dispatch: _dispatch
      });
    };
  };
}

精简的30行代码,设计思想强无敌。不难看出applyMiddleware这个函数接收一个createStore函数返回一个接收参数和createStore一样的函数。如下图是createStore的部分源码:

enhancer就是applyMiddleware执行完第一层后的函数,传一个createStore函数,再次返回一个函数,但此时只传外层的reducer和preloadedState,却没在传第三个enhancer参数。这里要看回到applyMiddleware函数

两层形参对应上面的实参,可以看到applyMiddleware内部还调用了createStore,整个一个完整的逻辑如下(部分重要代码):

首先是调用createStore,这个enhancer其实就是applyMiddleware(middleware1, middleware2)。

const store = createStore(
    reducer,
    undefined,
    enhancer
  )

其次是createStore里判断执行enhancer,如果传了enhancer,那就对enhancer执行再执行,且第二次执行不传enhancer,这里return的其实也是applyMiddleware函数的返回值,但是等下在applyMiddleware里还会在执行一次createStore。

if (typeof enhancer !== 'undefined') {
    if (typeof enhancer !== 'function') {
      throw new Error('Expected the enhancer to be a function.');
    }

    return enhancer(createStore)(reducer, preloadedState);
  }

最后是applyMiddleware里的,由于createStore上面最后一次执行未传enhancer,所以applyMiddleware里的createStore是不会再次执行enhancer,不然就死循环了。拿到返回的sotre对象,重新改造dispatch并返回,这就是中间件的实现的一个大体流程。

  return function (createStore) {
    return function (reducer, preloadedState, enhancer) {
      var store = createStore(reducer, preloadedState, enhancer);
      //省略一万行
    }
  }

至此,相信大家也差不多理解了createStore和applyMiddleware相互之间的关系了,其实关于中间件为什么嵌套三层的问题也自然而然的解开了,一张图片来说明吧。

菜鸟学习笔记,如有不对,还希望高手指点。如有造成误解,还希望多多谅解。

著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。

-------------本文结束感谢您的阅读-------------

本文标题:理解applyMiddleware和createStore之间的关系

文章作者:

发布时间:2017年08月01日 - 11:08

最后更新:2018年11月29日 - 13:11

原始链接:https://jiangjinjin1.github.io/2017/08/01/%E7%90%86%E8%A7%A3redux%E4%B8%AD%E7%9A%84applyMiddleware%E4%B8%8E%E4%B8%AD%E9%97%B4%E4%BB%B6/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

自己留着当笔记

欢迎关注我的其它发布渠道