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
}
複製代碼
參數store
與action
咱們都很熟悉,next
實際上指的就是dispatch
,這個中間件的做用是打印日誌,在action
發起以前和以後打印一些信息,執行next
就是執行真正的dispatch
去更新數據。咱們再來看下applyMiddlewar
e這個函數作了什麼,爲何中間件要這麼寫。數組
// 警告:這只是一種「單純」的實現方式!
// 這 *並非* 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
返回的時候把store
的dispatch
變成了嵌套不少層的dispatch
。app
當咱們毎執行一個dispatch
時,它會先調用了嵌套不少層的dispatch
,最後再執行真正的dispatch
去更新數據,如今咱們掌握了中間件爲啥要那麼寫了。異步
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-saga
。ui