淺析`redux-thunk`中間件源碼

總以爲文章也應該是有生命力的,歡迎關注個人Github上的博客,這裏的文章會依據我本人的見識,逐步更新。html

大多redux的初學者都會使用redux-thunk中間件來處理異步請求,其理解簡單使用方便(具體使用可參考官方文檔)。我本身其實也一直在用,最近偶然發現其源碼只有一個函數,考慮到其在Github上至今有6747個贊,所以比較好奇它究竟給出了一個怎麼樣的函數。react

什麼是thunk?

在看具體的源碼以前,咱們先看一個詞thunk,理解這個詞有助於咱們理解源碼。git

A thunk is a function that wraps an expression to delay its evaluation.
維基百科中是這樣解釋thunk的:thunk是一種包裹一些稍後執行的表達式的函數。github

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行。最後三行模塊的導出方法很好理解,express

// 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同樣,以下:redux

({ dispatch, getState }) => next => action => {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }
    return next(action);
  }

上述代碼使用函數參數的解構加上連用三個箭頭函數,顯得很是簡潔,單同時也帶來了理解的困難(這也是箭頭函數的缺點之一)。把上述代碼在babel REPL中轉譯爲ES5語法後,咱們看到如下結果:babel

"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又是什麼?app

咱們先看看,在reudx中咱們如何使用中間件:異步

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,以後有時間會再總結一下它的用法,若是能夠,也願意再分析下它的源碼,歡迎關注。

相關連接

相關文章
相關標籤/搜索