在使用redux管理異步數據流的時候,咱們會使用中間件,以redux-thunk中間件爲例,咱們作一下分析:ajax
首先是構建store,咱們須要如下代碼進行揉入中間件的相似creatStore函數的構造:json
const loggerMiddleware = createLogger(); const createStoreWithMiddleware = applyMiddleware( thunkMiddleware, loggerMiddleware )(createStore); export default function configureStore(initialState) { return createStoreWithMiddleware(rootReducer, initialState); }
在這段代碼中,咱們用到了 redux
applyMiddleware 函數去將中間件揉入構造store的工廠函數中,
applyMiddleware函數的源碼以下所示:
import compose from './compose' export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, initialState, enhancer) => { var store = createStore(reducer, initialState, enhancer) var dispatch = store.dispatch var chain = [] var middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) } chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) return { ...store, dispatch } } }
先看函數的return,咱們經過applyMiddleware構建獲得的createStoreWithMiddleware函數實際上是這樣一個函數
function (reducer, initialState, enhancer){ ....... return { ...store, dispatch } }
而store就是它return出來的這個對象數組
store的創建流程大體就是這樣,但此時store的dispatch方法已經不是原來的dispatch,注意下面的代碼:數據結構
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
這纔是 applyMiddleware 方法的核心,它將每一個middleware進行處理,並存入到chain 的數組中,而後調用compose方法對chain數組進行處理,處理出來的返回值就是store的dispatch,也就是咱們在業務代碼中用到的dispatchapp
接下來看一下compose方法作了什麼:異步
export default function compose(...funcs) { if (funcs.length === 0) { return arg => arg } else { const last = funcs[funcs.length - 1] const rest = funcs.slice(0, -1) return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args)) } }
它經過調用數組的reduceRight方法對各個中間件進行整合函數
reduceRight方法的 第一參數是 callback(preValue,curValue) ,第二個參數是要傳遞給callback做爲第一個參數preValue來使用的fetch
這時咱們回到applyMiddleware方法中的這段代碼:jsonp
var middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) } chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
由此咱們能夠知道傳給last(...args)的正是 store.dispatch
咱們根據官方文檔能夠知道中間件的通用構造以下:(箭頭函數這裏略過)
function middleware({dispatch, getState}) { return function (next) { return function (action) { return next(action); } } }
chain數組裏面的數據結構是這樣的 :[ function(next){return function(action){...}},function(next){return function(action){...}} ...]
也就是 middleware函數的裏面一層 的這個函數
function (next) { return function (action) { return next(action); } }
而後再通過compose的進一步reduceRight提煉:
return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args))
compose就是 function(action){return next(action)}
在通過 f(composed) 還是 function(action){return next(action);} 只不過這裏的next是上一個中間件的返回值,追溯源頭,next其實就是 store.dispatch一路通過f(composed)這種方式將中間件的方法揉和進來的變種dispatch
因此通過揉入中間件的createStore工廠函數返回的store對象的dispatch方法,其實就是function(action){return next(action);}
而後結合實際中咱們使用redux-thunk進行異步數據操做,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; //箭頭函數轉變正常就是這樣 function createThunkMiddleware(extraArgument) { return function({ dispatch, getState }){ return function(next){ return function(action){ if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); } } }; }
經過上面分析,咱們的store.dispatch就是這個東西
function(action){ if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }
咱們在調用異步獲取數據的時候 action是這樣寫的:
export function fetchUri(key){ return function(dispatch){ dispatch(request("show")); return $.ajax({ url:BOOKLIST_REQ.uri, dataType:"jsonp", data:{q:key,count:BOOKLIST_REQ.count} }).done(res=>{ dispatch(receive(res)); dispatch(request("hidden")); }).fail(res=>console.error(res)); }; }
激發調取異步數據方法是 store.dispatch(fetchUrl("xxx"));
這樣後面的就不用細說了,怎麼執行下來就一目瞭然了吧
這就是整個中間件大體的工做過程,若是有什麼說的不對的地方,你特麼來打我呀!