redux-thunk中間件源碼

淺析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,getStatenext還有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中確實包含getStatedispatch兩項,next則來自dispatch = compose(...chain)(store.dispatch)這一句中的store.dispatch,而actiondispatch某個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,以後有時間會再總結一下它的用法,若是能夠,也願意再分析下它的源碼,歡迎關注。

相關文章
相關標籤/搜索