redux中的middleware

1 使用

const store = createStore(
  rootReducer,
  applyMiddleware(
    thunkMiddleware, // lets us dispatch() functions
    loggerMiddleware // neat middleware that logs actions
  )
)

其中applyMiddleware(...)是一個enhancer。enhancer在redux中的做用會代理createStore方法返回具備加強效果的store.redux

applyMiddleware接收一系列middlewares。一個典型的middleware是長這樣的:app

export default function thunkMiddleware({ dispatch, getState }) {
  return next => action => {
    if (typeof action === 'function') {
      return action(dispatch, getState);
    }

    return next(action);
  };
}

applyMiddleware在接收到middleware後,會進行以下處理:函數

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

    var middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    }
    // 將middleware初始化,些時chain裏是Array<next=>action=>doSomething>
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

重點是後面的compose語句。compose的實現很是簡單:spa

export default function compose(...funcs) {
  return (...args) => {
    if (funcs.length === 0) {
      return args[0]
    }

    const last = funcs[funcs.length - 1]
    const rest = funcs.slice(0, -1)

    return rest.reduceRight((composed, f) => f(composed), last(...args))
  }
}

接收一堆參數fns,返回另外一個函數。在這個函數裏,將參數中的函數逐個從右到左執行,上一個執行的結果將作爲下一個執行的參數。代理

compose(f, g, h)(100)至關於f(g(h(100))). 而對於上面的dispatch = compose(...chain)(store.dispatch),因爲chain中的每個函數的結構均爲:rest

function g(next) {
  return  function (action) {
     // do something
  }
}

對於函數g,執行g(dispatch)至關於返回一個函數:code

function (action) {
  // 這個函數中,next的值爲dispatch
}

所以,對於d = compose(f, g)(dispatch),即至關於返回了一個函數:get

  • 這個函數長的是這樣的: function f1(action) {/* 函數體中的next爲g1*/}it

  • g1的定義是function g1(action) {/* 函數體中的next爲dispatch*/}io

這樣經過調用d,層層next下去,最終就調到了dispatch了。
注:因爲上面的chain = middlewares.map(middleware =>middleware(middlewareAPI)),每個middleware都能直接訪問到store.dispatch,每一個middleware均可以在任意時刻進行dispatch,之因此最後一個next被弄成了dispatch,可能只是爲了讓默認行爲是dispatch.

相關文章
相關標籤/搜索