從源碼角度理解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));
    };
  });
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章