解讀只有99行的Redux(二)—— 中介軟體相關

weixin_33806914發表於2018-05-13
4613793-da123fbc657c0734.png
redux

原文釋出在我的個人部落格 解讀只有99行的Redux(二) | 以太空間

一、概述

  在使用Redux的時候我們可能會遇到非同步操作的問題,希望讓 Reducer 在非同步操作結束後自動執行,所以我們就用了中介軟體(middleware)。
  先看一下中介軟體的一般形式:

const middleware = store => reducer => next => {
    ...//這一行可能會獲取store的state並使用
    let result = next(action);
    ...//這一行可能會獲取store的state並使用
    return result
}

  在真正的Redux環境中,我們一般是這樣使用中介軟體的:

const { createStore, applyMiddleware} = Redux

const store = createStore(reducer,
    applyMiddleware(loggerMiddleware, confirmationMiddleware)
);

  不過,因為我們現在解讀的是slim-redux,所以我們這樣使用

const { createStore, applyMiddleware} = Redux

const store = applyMiddleware(
    loggerMiddleware,
    confirmationMiddleware)(createStore)(reducer);

二、compose解讀

export function compose(...funcs) {
  return arg => funcs.reduceRight((composed, f) => f(composed), arg);
}

  要想理解下面的applyMiddleware,就得先搞懂這個compose
  它的作用就是從右到左來組合多個函式,這是函數語言程式設計中的方法,為了方便,被放到了 Redux 裡。
  它需要合成的多個函式。預計每個函式都接收一個引數。它的返回值將作為一個引數提供給它左邊的函式,以此類推。例外是最右邊的引數可以接受多個引數,因為它將為由此產生的函式提供簽名。
  compose(funcA, funcB, funcC) 形象為 compose(funcA(funcB(funcC())))

三、applyMiddleware解讀

export function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, initialState) => {
    var store = createStore(reducer, initialState);
    var dispatch = store.dispatch;
    var chain = [];

    chain = middlewares.map(middleware => middleware({
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    }));
    dispatch = compose(...chain)(store.dispatch);

    return { ...store, dispatch };
  };
}

  applyMiddleware是一個高階函式,我們從最內層的函式開始:
  首先呼叫createStore得到了一個store,然後儲存這個storedispatchdispatch,再宣告一個chain陣列。
  對最外層函式applyMiddleware的剩餘引數middlewares進行遍歷,對每一個middleware,傳入一個臨時store{getState: store.getState, dispatch: (action) => dispatch(action)}作為引數呼叫它。根據上面middleware的形式,其結果是以下的形式的函式

function (next) {
    return function (action) {
        return next(action);
    };
}

  遍歷結束後,chain陣列裡面每個元素都是類似上面這樣的函式。

  最後使用compose函式將chain陣列裡面的每個函式元素組合起來最後傳入store.dispatch
  整個呼叫過程類似下面的結構:

function (next1) {
  return function (next2) {
      return function (next3) {
          return next4(store.dispatch);
      }
  }
}

  經過層層封裝,dispatch已經不是原來的dispatch。呼叫這個dispatch的時候,我們想要的功能都會在中間完成,整個呼叫過程如下圖所示:

4613793-f2489e71d2e65977
onion

  最後解構store並返回,新的dispatch覆蓋原來的dispatch

  以下是解讀只有99行的Redux系列的其他兩篇文章

  解讀只有99行的Redux(一) 從建立一個store開始
  解讀只有99行的Redux(三) 輔助函式和組合Reducer

相關文章