redux-thunk
中間件源碼大多redux
的初學者都會使用redux-thunk
中間件來處理異步請求,其理解簡單使用方便(具體使用可參考官方文檔)。我本身其實也一直在用,最近偶然發現其源碼只有一個函數,考慮到其在Github上至今有6747個贊,所以比較好奇它究竟給出了一個怎麼樣的函數。html
thunk
?在看具體的源碼以前,咱們先看一個詞thunk
,理解這個詞有助於咱們理解源碼。react
A thunk is a function that wraps an expression to delay its evaluation. 維基百科中是這樣解釋
thunk
的:thunk
是一種包裹一些稍後執行的表達式的函數。git
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;
redux-thunk
的源碼很是簡潔,出去空格一共只有11行,這11行中若是不算上}
,則只有8行。最後三行模塊的導出方法很好理解,github
// thunk的內容以下 ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); } // thunk.withExtraArgument的結果以下 function createThunkMiddleware(extraArgument) { return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; }
thunk.withExtraArgument
容許給返回的函數傳入額外的參數,它比較難理解的部分和thunk
同樣,以下:express
({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }
上述代碼使用函數參數的解構加上連用三個箭頭函數,顯得很是簡潔,單同時也帶來了理解的困難(這也是箭頭函數的缺點之一)。把上述代碼在babel REPL中轉譯爲ES5語法後,咱們看到如下結果:redux
"use strict"; function createThunkMiddleware(extraArgument) { return function (_ref) { var dispatch = _ref.dispatch, getState = _ref.getState; return function (next) { return function (action) { if (typeof action === "function") { return action(dispatch, getState, extraArgument); } return next(); }; }; }; }
這下,代碼一會兒咱們能看懂了,不過稍等這裏的dispatch
,getState
,next
還有action
又是什麼?babel
咱們先看看,在reudx
中咱們如何使用中間件:app
let store = createStore( reducer, applyMiddleware(thunk) );
看來,要解開dispatch
,getState
,next
,action
從哪裏來,咱們還須要再看看applyMiddleware
的源碼,以下:異步
export default function applyMiddleware(...middlewares) { return (createStore) => (...args) => { const store = createStore(...args) let dispatch = store.dispatch let chain = [] const middlewareAPI = { getState: store.getState, dispatch: (...args) => dispatch(...args) } chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) return { ...store, dispatch } } }
能夠看出其中middleware
執行時傳入的參數對象middlewareAPI
中確實包含getState
和dispatch
兩項,next
則來自dispatch = compose(...chain)(store.dispatch)
這一句中的store.dispatch
,而action
在dispatch
某個action
時傳入。函數
通常來講一個有效攜帶數據的action
是以下這樣的:
{
type: ADD_TODO, text: 'Build my first Redux app' }
加入redux-thunk
後,action
能夠是函數了,依據redux-thunk
的源碼,咱們能夠看出若是傳入的action
是函數,則返回這個函數的調用,若是自己傳入的函數是一個異步函數,咱們徹底能夠在函數調用結束後,獲取必要的數據再次觸發dispatch
由此實現異步效果。
redux-thunk
的源碼總的來講仍是很簡單的,理解這個函數自己並不難,可是在完全弄懂每一項卻須要對reudx
的部分源碼有所瞭解。react官方文檔中的Middleware一節講解的很是好,也確實幫我理解了中間件的工做原理,很是推薦閱讀。以前一直使用redux-thunk
作異步處理,這段時間嘗試了一下redux-saga
,它很是優雅,可用於處理更加複雜的異步action,以後有時間會再總結一下它的用法,若是能夠,也願意再分析下它的源碼,歡迎關注。