从源码角度理解Redux中间件---applyMiddleware

什么是中间件

在redux中,我们可以在view层dispatch一个action,action到达store中的reducer,reducer根据action的type更新处理state,从而更新store中的数据。但是redux并不能处理异步的dispatch。这时候我们就需要使用redux提供的applyMiddleware对dispatch进行增强,使我们的dispatch可以异步。
这里重点讨论applyMiddleware这个中间层,是如何工作的。

中间件的使用

const store = createStore(myReducer, applyMiddleware(logger, thunk));

分析下源码,createStore是如何使用这个applyMiddleware的勒?看看下面这段源码yourProject\node_modules\[email protected]@redux\lib\redux.jsapplyMiddleware(logger, thunk)执行的结果就是enhancer,作为一个增强器去包装处理reducer。

function createStore(reducer, preloadedState, enhancer) {
  ···
  if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
    enhancer = preloadedState;
    preloadedState = undefined;
  }
  ···
    return enhancer(createStore)(reducer, preloadedState); // 关键代码
  }

那咱们接下来看看applyMiddleware(logger, thunk)执行的结果enhancer是个什么呢?

中间件applyMiddleware做了什么

源码地址也是在这里哦,yourProject\node_modules\[email protected]@redux\lib\redux.js

// 中间件
function applyMiddleware() {
  // 将fn参数收集到middlewares,这是一个fn数组
  for (var _len = arguments.length, middlewares = new Array(_len), _key = 0; _key < _len; _key++) {
    middlewares[_key] = arguments[_key];
  }
  
  // 返回一个函数,enhancer,看看enhancer的调用,enhancer(createStore)(reducer, preloadedState);
  return function (createStore) {
  	// 又返回一个函数,此时参数为(reducer, preloadedState)
    return function () {
      // 利用初始reducer,创建store,这个store和咱们没有用中间件的时候一样哦~
      var store = createStore.apply(void 0, arguments);

      var _dispatch = function dispatch() {
        throw new Error('Dispatching while constructing your middleware is not allowed. ' + 'Other middleware would not be applied to this dispatch.');
      };
	  // 对store进行了简单的包装,用于拦截增强函数中的dispatch
      var middlewareAPI = {
        getState: store.getState,
        dispatch: function dispatch() {
          return _dispatch.apply(void 0, arguments);
        }
      };
      // 关键代码,遍历fn数组,将middlewareAPI(包装过的store)作为参数传递进去执行该函数
      var chain = middlewares.map(function (middleware) {
        return middleware(middlewareAPI);
      });
      // compose是一个基于reduce的方法,将fn数组进行套娃[fn1, fn2, fn3] => fn1(fn2(fn3(arguments)))
      // fn1(fn2(fn3(arguments)))的实参是真实原始的dispatch,真正意义上的对原始dispatch做增强
      _dispatch = compose.apply(void 0, chain)(store.dispatch);
      // 返回store,此时store拥有superDispatch啦!
      return _objectSpread2({}, store, {
        dispatch: _dispatch
      });
    };
  };
}

// 组装器
function compose() {
  ···
  return funcs.reduce(function (a, b) {
    return function () {
      return a(b.apply(void 0, arguments));
    };
  });
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章