Redux中間件(二) - 如何自己寫(xiě)一個(gè)中間件

前言

最近看了一下Redux的官方文檔,突然感覺(jué)以前忽略了很多東西,現(xiàn)在回頭看看,正好記錄一下,并且加深印象

中間件的使用

  const store = createStore(reducers,applyMiddleware(logger));

以上是應(yīng)用了redux-logger中間件的代碼,只要按照官方提供的規(guī)定格式實(shí)現(xiàn),并應(yīng)用到中間件方法,那么,在執(zhí)行一個(gè)action的時(shí)候,就會(huì)調(diào)用中間件。

在官方的示例中,有一個(gè)logger實(shí)現(xiàn)的示例

const logger = store => next => action =>{
    console.log('prev state',store.getState())
    console.log('dispatch',action);

    let result = next(action);

    console.log('next state',store.getState());

    return result;
}

從這個(gè)示例可以看出,實(shí)現(xiàn)一個(gè)中間件需要做一下幾件事情:

  1. 三層函數(shù)包裝:第一層傳入store,第二層傳入下一個(gè)中間件next,第三層傳入此次執(zhí)行的action;

2.在最內(nèi)層的函數(shù)實(shí)現(xiàn)中,需要調(diào)用next中間件,并返回結(jié)果。

原理解析

首先來(lái)看一下createStore

  1. createStore(reducer, preloadedState, enhancer)
    createStore有三個(gè)參數(shù)1.reducer;2.preloadedState;3.enhancer

reducer :即一些改變state的純函數(shù),這個(gè)可以在官方文檔查看具體定義;

preloadesState:是初始化的state,這個(gè)state可以是加載頁(yè)面時(shí)從服務(wù)器提供的初始化state值,這個(gè)為服務(wù)器端渲染,并與客戶端保持?jǐn)?shù)據(jù)一致提供可能;

enhancer: store增強(qiáng)功能,在redux中特指applyMiddleware()方法的返回值;

來(lái)看看createStore方法的開(kāi)頭部分

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)
  }

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

這里面第二個(gè)判斷if中有enhancer為function則調(diào)用enhander(createStore)(reducer,preloadedState);我們都知道enhancer 是applyMiddleware方法的返回值,
下面在看applyMiddleware方法

  1. applyMiddleware(...middlewares)

參數(shù)即為所有要使用的符合redux的中間件;
apllyMiddleware的代碼很精簡(jiǎn)

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: (action) => dispatch(action)
    }
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

來(lái)分析一下applyMiddleware方法,

  1. 接收一個(gè)middleware數(shù)組作為參數(shù),返回一個(gè)方法,我們暫且叫它enhancer;
  2. enhancer仍然是一個(gè)方法,他接收createStore方法作為參數(shù),enhancer方法返回的還是一個(gè)方法,這個(gè)方法的參數(shù)與createStore方法的的簽名一樣,都包含三個(gè)參數(shù),分別是reducer, preloadedState, enhancer;我們叫它mergeDispatch;
  3. mergeDispatch這個(gè)最終的方法的作用有2點(diǎn),首先調(diào)用createStore創(chuàng)建store,然后就是不斷的替換store.dispatch,以達(dá)到應(yīng)用中間件的目的,大概流程如下:
QQ圖片20170903151553.jpg

最終就是把原始的store.dispatch應(yīng)用到所有的中間件的最核心的位置調(diào)用,其他的插件都在原始的dispatch外層包裹著。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容