redux源碼分析之五:applyMiddleware

歡迎關注redux源碼分析系列文章:
redux源碼分析之一:createStore.js
redux源碼分析之二:combineReducers.js
redux源碼分析之三:bindActionCreators.js
redux源碼分析之四:compose.js
redux源碼分析之五:applyMiddlewareredux

redux中間件其實很是簡單,中間件的目的只有一個:在dispatch先後,執行一些代碼,達到加強dispatch的效果,有點相似裝飾器的原理。segmentfault

applyMiddleware須要結合createStore函數來看,appleyMiddleware就是createStore的第三個參數enhancer,好比,對redux-logger中間件,其使用方式以下:api

import { applyMiddleware, createStore } from 'redux';
import { createLogger } from 'redux-logger';

const logger = createLogger();
const store = createStore(
  reducer,
  applyMiddleware(logger)
)

applyMiddleware文件的源碼以下:app

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

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

    return {
      ...store,
      dispatch
    }
  }
}

1、applyMiddleware函數的參數

  1. 接受多個參數,每個參數,都是一箇中間件

2、函數的返回值

函數的返回值自己,也是另一個函數,而這個函數,接受的參數是createStore,結合createStore的前幾行源碼來看:函數

export default function createStore(reducer, preloadedState, enhancer) {
  if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
    enhancer = preloadedState
    preloadedState = undefined
  }

  if (typeof enhancer !== 'undefined') {
    if (typeof enhancer !== 'function') {
      throw new Error('Expected the enhancer to be a function.')
    }

    return enhancer(createStore)(reducer, preloadedState)
  }
  //其他代碼這裏忽略
}

能夠看到,createStore的第三個參數ehancer若是是一個函數的話,就會優先執行ehancer,而後再再enhancer內部調用createStore函數,因此,createStore其實只會執行一些,也只會生成一個store。源碼分析

3、關鍵代碼解釋

我添加了代碼註釋以下:(關於compose函數的解釋,請參考文章:redux源碼分析之四:compose.js):spa

export default function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, preloadedState, enhancer) => {
    //這裏會原封不動的執行createStore,並根據入參生成一個store
    const store = createStore(reducer, preloadedState, enhancer)
    //把dispatch從store中取出來
    let dispatch = store.dispatch
    let chain = []
    
    //這裏約定了全部的redux中間件只能使用的api就是2個,getState和dispatch
    const middlewareAPI = {
      getState: store.getState,
      dispatch: (...args) => dispatch(...args)
    }
    對每個中間件,執行中間件函數,並將中間件api對象傳入函數,用chain變量接收中間件執行結果的其返回值
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    //這裏用到了compose函數,分別按順序從後往前執行每個中間件,而且前一箇中間件的返回值做爲後一箇中間件的入參,全部中間件的第一個入參是原始的store.dispatch
    dispatch = compose(...chain)(store.dispatch)

    //最後返回store對象,只是,使用了通過中間件加工過的dispatch對象,替換掉原始的dispatch對象
    return {
      ...store,
      dispatch
    }
  }
}

4、總結

redux中間件只有一個目的:在dispatch先後,執行一些代碼,達到加強dispatch的效果,有點相似裝飾器的原理。,理解好了這一點就ok了。
下一篇文章會給你們帶來一個最簡單的redux中間件,敬請期待。code

相關文章
相關標籤/搜索