對Redux中間件的理解

中間件的用途

Redux中間件叫middleware,主要是在Redux發起一個Acttion還沒到達Reducer以前或者Reducer執行以後作一些處理,例如記錄日誌、發起請求等,完成以後再調用真正的diapatch更新數據,用法以下:javascript

import { createStore, combineReducers, applyMiddleware } from 'redux'

let todoApp = combineReducers(reducers)
let store = createStore(
  todoApp,
  // applyMiddleware() 告訴 createStore() 如何處理中間件
  applyMiddleware(logger, crashReporter)
)
複製代碼

createStore時傳入applyMiddleware函數,而applyMiddleware參數正是中間件,這樣在每次diapatch的時候會先執行中間件的邏輯。java

實現原理

在瞭解中間件如何使用後,咱們再來看一下它是如何實現的,首先咱們來看下中間件的具體寫法。redux

const logger = store => next => action => {
  console.log('dispatching', action)
  let result = next(action)
  console.log('next state', store.getState())
  return result
}
複製代碼

參數storeaction咱們都很熟悉,next實際上指的就是dispatch,這個中間件的做用是打印日誌,在action發起以前和以後打印一些信息,執行next就是執行真正的dispatch去更新數據。咱們再來看下applyMiddleware這個函數作了什麼,爲何中間件要這麼寫。數組

// 警告:這只是一種「單純」的實現方式!
// 這 *並非* Redux 的 API.

function applyMiddleware(store, ...middlewares) {

  let dispatch = store.dispatch
  middlewares.forEach(middleware =>
    dispatch = middleware(store)(dispatch)
  )
    return { ...store, dispatch }
}
複製代碼

這個並非applyMiddleware真正寫法,之因此這麼寫,只是爲了便於理解applyMiddleware的實現原理。咱們傳入了不少中間件middlewares,而後再用數組去遍歷它。middleware(store)(dispatch)這裏就是調用了const logger = store => next => action => {}store => next這一層,最返回的是一個函數。這裏很是巧妙,執行下標爲0的middleware傳入store.dispatch,而後再把dispatch變爲下標爲0的middleware返回的函數,執行下標爲1的的middleware,再把下標爲0的middleware返回的函數diapatch做爲參數傳給下標爲1的的middleware,以此類推下去,最終的效果就是嵌套了不少層。最後applyMiddleware返回的時候把storedispatch變成了嵌套不少層的dispatchapp

當咱們毎執行一個dispatch時,它會先調用了嵌套不少層的dispatch,最後再執行真正的dispatch去更新數據,如今咱們掌握了中間件爲啥要那麼寫了。異步

Redux-thunk源碼解析

Redux-thunk是解決異步調用的一箇中間件,它的源碼很是簡單,話很少說,咱們來看一下它的源碼:函數

function createThunkMiddleware(extraArgument) {
  // 這裏纔是真正的中間件
  return ({ dispatch, getState }) => (next) => (action) => {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }

    return next(action);
  };
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;
複製代碼

咱們重點看action,咱們通常dispatch(action)action通常爲普通對象,這裏卻判斷action的類型若是是一個方法,就執行它。Redux-thunk的做用顯而易見了,將action改寫爲一個函數,這裏通常爲異步函數,能夠返回一個promsie,結束後在調用普通的dispath去更新數據。Redux-thunk雖然解決了異步調用的問題,可是同時也違背了只能dispatch一個action的原則,而且它不夠強大,如今解決異步調用通常都是用Redux-sagaui

相關文章
相關標籤/搜索