理解Redux中間件

間件是什麼

若是你用過express.js之類的web框架,對中間件(Middleware)這個概念可能不會陌生。中間件其實就是一種獨立運行於各個框架組件之間的膠水代碼。在Express.js或Koa等框架中,中間件一般是運行在收到請求處處理請求之間,但是實現日誌記錄、身份認證等預處理操做。而在Redux裏,中間件是運行在action發送出去,到達reducer之間的一段代碼。html

編寫中間件

日誌記錄是開發過程當中經常使用的一個功能,你能夠選擇侵入業務邏輯來記錄日誌(不推薦),也能夠選擇使用中間件來實現這個功能。接下來讓咱們編寫一個經常使用的日誌記錄中間件:web

const loggerMiddleware = store => next => action => {
  console.group(action.type);
  console.log('action: ', action);
  const result = next(action);
  console.log('next state: ', store.getState());
  console.groupEnd(action.type);
  return result;
}

使用中間件的時候,要在初始化store的時候利用applyMiddleware注入進去:express

const store = createStore(
    rootReducer,
    applyMiddleware(loggerMiddleware)
)

這樣,咱們在每次觸發action的時候就能記錄咱們所須要的信息。一樣的方式,也能夠實現日誌上報等功能。編程

組合中間件

中間件實際上是一種高層次的抽象,能夠將核心領域業務和基礎架構邏輯解耦開來。而多箇中間件能夠組合使用,從而使每個中間件可以保持「小而美」的特性。架構

const store = createStore(
    rootReducer,
    applyMiddleware(thunk, loggerMiddleware)
)

其中applyMiddleware函數能夠接收多箇中間件,源碼以下:app

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

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

    return {
      ...store,
      dispatch
    }
  }
}

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

  if (funcs.length === 1) {
    return funcs[0]
  }

  const last = funcs[funcs.length - 1]
  const rest = funcs.slice(0, -1)
  return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args))
}

咱們能夠看到它主要作了幾個工做:框架

  1. 返回一個高階函數,這個函數中會初始化store和重寫dispatch邏輯,以便後續使用。
  2. store.getState,dispatch傳入每一箇中間件中,並收集調用鏈結果。

以後在應用中全部使用的dispatch都將是修改過的邏輯,從中咱們能夠看出有點面向切面編程的味道,能夠好好體會一下。ide

相關文章
相關標籤/搜索