深度剖析github上15.1k Star項目:redux-thunk

2020-12-22 酷扯兒

本文轉載自【微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫

日益忙碌的一周又過去了,是時候開始每周一次的總結復盤了,今天筆者就來剖析一下github中star數15.1k的開源項目redux-thunk。

作為一名React方向的前端工程師,不管是被面試還是面試別人,大部分都會說起redux-thunk的實現原理,因為它非常經典且有用,而且代碼量少的感人,只有短短12行代碼,卻能解決React開發中同一個函數支持多dispatch和異步action的問題(雖然這完全依賴於redux的中間件機制(Middleware))。

接下來筆者將從:

Redux的工作機制中間件實現原理redux-thunk源碼實現這三個方面來帶大家徹底掌握redux-thunk源碼,從而對redux有更深入的了解和應用。

正文

在解讀Redux-thunk源碼之前我們需要先掌握redux的基本工作機制和中間件實現原理,這樣才能更好地理解源碼背後的奧義。長話短說我們先來看看redux的幾個核心api及其作用:

redux解決的真正問題是React組件間的狀態共享和狀態管理問題,通過以上的6個核心api我們便能管理複雜的狀態,並能監聽和追溯狀態的改動。機制筆者總結如下:

redux工作機理基本了解之後,我們先看看一個實際的例子:

import actionType from './actionType'class Actions {static start() { return { type: actionType.CREATE_TODO_DOING } } static ok(data, cb) { cb && 'function' === typeof cb && cb(data); return { type: actionType.CREATE_TODO_SUCCESS, payload: data } } static fail(data, cb) { cb && 'function' === typeof cb && cb(data); return { type: actionType.CREATE_TODO_FAILURE, payload: data } }}

以上代碼我們可以發現我們用了一個統一的createAction來創建action,在調用時只需要執行Actions.start()即可,我們也知道action返回的是一個標準的對象,但我們可以在return之前做一些side effect。這裡我們並不能在action中處理異步邏輯,這也是redux-thunk的價值之一,即解決異步調用action。

到這一步我們仍然不能直接進入redux-thunk的源碼分析,因為我們還是不清楚如何解決上述步驟,因為我們還沒有了解redux的中間件機制。

redux中間件機制

說到中間件(middleware),使用過nodejs的人可能會很熟悉,比如說知名的koa中間件,express中間件等,其實中間件筆者的理解是在某個執行流中的某個環節做一些額外的處理的模塊。實現中間件的機制也很簡單, 就是在框架核心執行流中去遍歷外部傳入的中間件,並依次執行即可,我們先來看看redux中如何使用中間件的:

import { createStore, applyMiddleware } from 'redux';import reducers from './reducers';const middlewares = applyMiddleware(middleware1, middleware2);const store = createStore(reducers, middlewares);

所以說redux-thunk是被傳入applyMiddleware方法中作為參數使用的,不難猜到applyMiddleware方法中一定有遍歷執行參數的邏輯,我們來看看applyMiddleware的核心源碼:

export default function applyMiddleware(……middlewares) {return function enhancer(createStore) { return function enhancedCreateStore(……args) { const store = createStore(……args) let dispatch = () => { thrownewError('此處省略n個字……') } const middlewareAPI = { getState: store.getState, dispatch: (……args) => dispatch(……args) } const chain = middlewares.map(function(middleware) { return middleware(middlewareAPI) }) dispatch = compose(……chain)(store.dispatch) return { ……store, dispatch, } } }}

由上面的源碼可知,在chain這段代碼裡我們發現其存儲的是applyMiddleware方法參數傳入getState,dispatch後的調用結果。接下來在dispatch這段代碼中出現了compose函數, 熟悉函數式編程的朋友不難猜到其內部肯定是實現批處理chain的函數,並將store.dispatch泵送至其內部。上面源碼分析後我們知道每一次執行dispatch時,都會先經過middleware的「洗禮」。

我們再來看看compose函數的內部實現:

export default function compose(……funcs) {if (funcs.length === 0) { return arg => arg } if (funcs.length === 1) { return funcs[0] } return funcs.reduce(function(a, b) { return function (……args) { return a(b(……args)) } })}

由上面代碼可以看出compose最終返回的是一個函數,如果參數大於一時,我們採用reduce將上一個函數返回的結果傳給下一個函數參數,以此來實現之間的參數共享和傳遞,非常經典的設計。

在掌握了redux中間件實現原理之後, 我們再來看redux-thunk源碼就非常容易理解了。

redux-thunk源碼分析

我們先看看這個github中star數15.1k的源碼長啥子:

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的全部源碼了,是不是很nice~。在上面的介紹中我們了解到redux中間件機制使得我們可以在中間件中拿到必備的dispatch, getState,並且在執行之前已經調用了兩層middleware,此時我們可以解剖一下createThunkMiddleware,在第一次調用createThunkMiddleware是在chain階段,即上面源碼分析的:

所以這裡的next也就是第二次調用時的store.dispatch, 為了實現同一函數內能執行多次dispatch,我們會判斷如果action為函數,則執行action本身並把必要參數傳遞給它,否則則直接觸發dispatch,這樣我們就實現了支持action為函數並且支持異步多dispatch的功能了,讀到這還是非常感嘆其設計的優雅和簡潔,不經讓筆者感嘆:學好函數式,走遍天下都不怕!

相關焦點

  • 過萬star高星項目的秘密(GitHub速覽 Vol.39)
    作者:HelloGitHub-小魚乾雖然國外十一併不過國慶,但是本周的 GitHub 也稍顯疲軟,GitHub 周榜的獲 star 超過 1k 的項目寥寥無幾,本周新開源的項目更是屈指可數。用 C 編寫的 GitHub repo 周榜中,知名的兩大深度學習框架——Tensorflow 和 Pytorch 雖榜上有名但是二者相加 star 數也未破千,好在 Go 項目一向頗受歡迎,比如 GitHub 官方開源的 cli 則一周獲得超過 3k+ star,之前熱點趨勢推薦過的安全傳輸文件工具——croc 表現也很搶眼獲得了 2k+ star。
  • 推薦給IT新手的11個Docker免費上手項目
    1. spug地址: http s:// github.com/openspug/spugstar: 3.8kfork: 769使用3. drone地址: http s:// github.com/drone/dronestar: 21.3kfork: 2.1k一個基於 Docker
  • GitHub 熱點速覽:刷 LeetCode 的正確姿勢! - CSDN
    btw,項目剛開源 24 小時不到已獲得近 3k starGitHub 地址→https://github.com/cyrildiagne/ar-cutpaste1.2 亞馬遜工程師親測:coding-interview-university本周 star 增長數:850+coding-interview-university
  • Github Star 7.2K,超級好用的OCR數據合成與半自動標註工具,強烈...
    機器之心發布機器之心編輯部OCR 方向的工程師,一定需要知道這個 OCR 開源項目:PaddleOCR。12 月,它又帶來四大新發布與升級,核心內容先睹為快:全新發布數據合成工具 Style-Text:可以批量合成大量與目標場景類似的圖像,在多個場景驗證,效果均提升 15% 以上。
  • 10月份Github上熱門的開源項目
    10月份GitHub上最熱門的Java開源項目排行已經出爐啦,一起來看看上榜詳情吧:1. base-adminhttps://github.com/huanzi-qch/base-adminStar 1499Base Admin一套簡單通用的後臺管理系統
  • 徹底讓你理解redux
    這裡拿一個簡單的例子說明下,為什麼說簡單的例子呢,因為簡單到不應該使用redux。。。 運行效果如圖(學習redux這個例子被介紹爛了):項目的運行效果大家應該能猜到哈,猜不到的clone下項目几几運行下:-) 所以這裡的如說問你,這個應用應該存在數據裡什麼數據呢?
  • 2020年10月份Github上熱門的開源項目
    11-17 13:46:44 來源: JEECG 舉報   2020年10月份Github上熱門的開源項目
  • AI消除馬賽克,GitHub開源項目上線三天收穫近...
    最近,一個名為 Depix 的 GitHub 項目爆火,上線三天 star 量已經高達 6.9k。項目作者 Sipke Mellema 是一名信息安全顧問。項目地址:https://github.com/beurtschipper/DepixDepix 能夠從像素化圖像截圖中恢復原圖中包含的文字密碼。
  • 72000 Star 下載工具被 GitHub 下架,背後的數字千年版權法案是什麼?
    高 Star 項目被下架,誰之過?日前,擁有72k+ star 的命令行視頻下載工具 youtube-dl 被 GitHub 下架,原因是受到了數字千年版權法案的限定,服務平臺有責任對於違反規定的軟體進行下架處理。
  • 周獲4700 Star 全球疫情數據可視化系統,超輕量級中文 OCR...
    COVID-19,或是 Google Drive 升級版可備份的雲盤項目 MyDrive 都交上了不錯的成績單,500,1,000,2,000…這是本周 GitHub 新生項的成績單,當然老而彌堅的 GitHub 老項目表現也不錯,你可以在本周的 #尚能星否 GitHub 老項目# 看到他們不孬的表現,當然本周的安全主題收錄的 3 個項目也是高 star 項,值得一馬。
  • Exodus Redux KODI電影插件3月推薦
    2.選擇文件管理5.輸入源地址:    https://i-a-c.github.io/ 點擊確定14.進入repo後,找到 repository.exodusredux-0.0.8.zip,點擊確定15.進入從庫安裝
  • github 商城 微信小程序專題及常見問題 - CSDN
    1:仿豆瓣電影微信小程序https://github.com/zce/weapp-demo2:微信小程序移動端商城https://github.com/liuxuanqiang/wechat-weapp-mall3:Gank微信小程序https://github.com/lypeer/wechat-weapp-gank
  • 韓國選秀節目之K-pop star系列
    前面我們盤點了韓國選秀節目sixteen和produce101,今天來盤點下k-pop star系列。k-pop star是SBS聯合3大社(SM&JYP&YG)的選秀節目,從2011年第一季開始,到2016年第六季結束。
  • 一天1300 Star量,GitHub上新官方命令行工具
    ——不是我說的 小編私以為,Git 是世界上最好的代碼版本控制工具,木有之一。在做項目的時候,通常我們會在本地寫代碼,並通過 Git 命令行追蹤所有修改痕跡。如果你想託管或開源,也可以直接用 Git 把整個項目推送到 GitHub 上。
  • GitHub很香,被中文霸榜了,但是...
    作為全球最大的開源社區,GitHub 對於程式設計師群體而言像是空氣般重要的存在,從代碼託管、項目管理到面試加成,可以說貫穿了程式設計師的職場生涯, 好,我去看了github開發榜榜單,的確看到中國的排名一直靠前。
  • GitHub 標星 32.7 k!一行命令下載全網視頻,這個項目牛逼了!
    網際網路上有很多類似優質的視頻,也有一些學習教程,如何把他們下載下來,保存到本地呢?這個問題,肯定不少同學需求過解決辦法,但都最終無果。我五一期間找到了一個 GitHub 項目可完美解決這個問題,標星 37.2k,一行命令下載全網視頻,太香了!
  • GitHub上star超1.2k的vue表格組件,功能太多又實用
    組件名稱:vxe-table項目地址:Github:https://github.com/xuliangzhan/vxe-table
  • 又一款基於Vue的數據可視化組件庫,Github上star超1.4k,太酷炫
    組件庫名稱:DataV項目地址:https://github.com/DataV-Team/DataVDataV是一個基於Vue的數據可視化組件庫(當然也有React版本)飛線圖/輪播表等其他組件npm安裝$ npm install @jiaminghi/data-view使用import Vue from 'vue'import DataV from '@jiaminghi/data-view'Vue.use(DataV)// 按需引入import { borderBox1
  • 最新GitHub前10的JavaScript開源項目分享
    3月份已經過去,是時候總結一波GitHub上最熱門的JavaScript開源項目啦
  • 最強下載神器 youtube-dl 「復活」,GitHub 7.5 萬 Star
    youtube-dl:廣受歡迎的下載神器youtube-dl 已經成為 GitHub 上最受歡迎的項目之一,擁有 7.5萬星,人氣介於 Node.js 及 Kubernetes 之間。2006發布,一開始只能從YouTube下載視頻和音頻,後來經過創作人員的不斷完善,下載支持的站點達到了1000多個,成為最受歡迎的下載神器。