學習過react的同窗確定都用過redux。瞭解redux數據流機制的action->dispatch->store->reduce->頁面交互其實很好理解,但是當咱們要用到異步請求或者打印日誌之類的副操做的時候,咱們沒法避免的會用到中間件Middleware。中間件都是怎麼執行以及如何有序的串在一塊兒很使人迷惑,下面我將嘗試解釋這個過程:react
假如你有個需求須要在分發dispatch先後打印不一樣狀態值,你確定會這麼想:redux
console.log('dispatching', action)
store.dispatch(action)
console.log('next state', store.getState())
複製代碼
封裝成函數:bash
function dispatchAndLog(store, action) {
console.log('dispatching', action)
store.dispatch(action)
console.log('next state', store.getState())
}
//執行
dispatchAndLog(store, action)
複製代碼
不妨改造store的dispatch更爲直接些:app
let next = store.dispatch
store.dispatch = function dispatchAndLog(action) {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
複製代碼
Redux把這個封裝的入口寫成了一個函數,就叫applyMiddleware。由此咱們明白了applyMiddleware的功能:改造dispatch函數,產生真假dispatch,而中間件就是運行在假真(dispatchAndLog假和next真)之間的代碼。異步
這裏咱們要對applyMiddleware進行一個準確的定義,它只是一個用來加工dispatch的工廠,而要加工什麼樣的dispatch出來,則須要咱們傳入對應的中間件函數(好比上例中的dispatchAndLog),下面咱們構造一個精簡版的applyMiddleware:函數
function applyMiddleware(middleware){
let next = store.dispatch;
store.dispatch = middleware(store)(next); // 這裏傳入store,是由於中間件中有可能會用到getState獲取數據,好比打印當前用戶等需求
}
}
applyMiddleware(dispatchAndLog)
複製代碼
中間件的功能各不相同,它們都要融入到dispatch中,在派發action的時候,按照順序一個個的執行,這是一個費腦經的事情。在上例中middleware會返回新的dispatch,咱們須要作的也就是將產生的新的dispatch傳遞個下箇中間件便可。以下:學習
function applyMiddleware(middleware,middleware2){
let next = store.dispatch;
store.dispatch = middleware2(middleware(store)(next));
// 這裏傳入store,是由於中間件中有可能會用到getState獲取數據,好比打印當前用戶等需求
}
}
applyMiddleware(dispatchAndLog,dispatchmethed)
複製代碼
以此類推有大量的中間件的時候咱們能夠這麼幹:ui
function applyMiddleware(...middlewares){
middlewares = middlewares.slice();
middlewares.reverse(); //執行順序是後到前,因此得倒置
let dispatch = store.dispatch
//循環嵌套
middlewares.foreach(function(middleware){
dispatch = middleware(store)(dispatch);
});
return Object.assign({}, store, { dispatch }); //合併dispatch到redux裏。
}
複製代碼
請注意這裏是一個循環嵌套的一個過程,因此中間的順序決定着中間件的執行順序。spa
總結兩點:日誌