近期阿寶哥在團隊內搞了一個 如何讀源碼 的專題,主要目的是讓團隊的小夥伴們瞭解讀源碼的思路與技巧。在此期間,阿寶哥也寫了 77.9K 的 Axios 項目有哪些值得借鑑的地方、從 12.9K 的前端開源項目我學到了啥 和 如何讓你的 Express 飛起來 三篇源碼解析的文章。其中前兩篇在 掘金社區 得到不錯的評價,平均 705+ 個 👍,因此阿寶哥就想寫一篇文章來分享一下本人讀源碼的思路、技巧與工具。javascript
好的,讓咱們開始出發吧!在進入正題以前,咱們先來個讀源碼前的 靈魂四連問 熱熱身。前端
既然前兩篇文章比較受你們喜歡,接下來阿寶哥就以最受歡迎的 Axios 爲例,來分享一下讀源碼的思路與技巧。java
Axios 是一個基於 Promise 的 HTTP 客戶端,同時支持瀏覽器和 Node.js 環境。它是一個優秀的 HTTP 客戶端,被普遍地應用在大量的 Web 項目中。ios
由上圖可知,Axios 項目的 Star 數爲 78.1K,Fork 數也高達 7.3K,是一個很優秀的開源項目,因此值得你們細細品讀。git
在確認 Axios 爲 「追求目標」 以後,下一步咱們就須要來發現它身上的優勢(特性):github
每一個人對 「美」 都有不一樣的見解,對於阿寶哥來講,我看中了圖中已選中的三點。所以,它們也很光榮地成爲讀源碼的三個切入點。固然切入點也不是越多越好,能夠先找本身最感興趣的地方做爲切入點。須要注意的是,若是切入點之間有關聯關係的話,建議作個簡單的排序。axios
選擇切入點以後,咱們就能夠開始逐一感覺 Axios 的設計之美。以 可以攔截請求與響應 這個切入點爲例,首先咱們就會接觸到 攔截器 的概念。因此咱們須要先了解攔截器是什麼、攔截器有什麼做用以及如何使用攔截器,這裏咱們能夠從項目的 官方文檔 或者項目中的 README.md 文檔入手。瀏覽器
Axios 提供了請求攔截器和響應攔截器來分別處理請求和響應,它們的做用以下:服務器
// 添加請求攔截器 —— 處理請求配置對象 axios.interceptors.request.use(function (config) { config.headers.token = 'added by interceptor'; return config; }); // 添加響應攔截器 —— 處理響應對象 axios.interceptors.response.use(function (data) { data.data = data.data + ' - modified by interceptor'; return data; }); axios({ url: '/hello', method: 'get', }).then(res =>{ console.log('axios res.data: ', res.data) });
在瞭解完攔截器的做用和用法以後,咱們就會把焦點聚焦到 axios 對象,由於註冊攔截器和發送請求都與它有緊密的聯繫。不過在看具體源碼以前,阿寶哥建議先對功能點作一下梳理。如下是阿寶哥的分析思路:函數
Axios 的做用是用於發送 HTTP 請求,請求攔截器和響應攔截器分別對應於 HTTP 請求的不一樣階段,它們的本質是一個實現特定功能的函數。這時咱們就能夠按照功能把發送 HTTP 請求拆解成不一樣類型的子任務,好比有 用於處理請求配置對象的子任務,用於發送 HTTP 請求的子任務 和 用於處理響應對象的子任務。當咱們按照指定的順序來執行這些子任務時,就能夠完成一次完整的 HTTP 請求。
既然已經提到了任務,咱們就會聯想到任務管理系統的基本功能:任務註冊、任務編排(優先級排序)和任務調度等。所以咱們就能夠考慮從 任務註冊、任務編排和任務調度 三個方面來分析 Axios 攔截器的實現。
// 添加請求攔截器 —— 處理請求配置對象 axios.interceptors.request.use(function (config) { config.headers.token = 'added by interceptor'; return config; }); // 添加響應攔截器 —— 處理響應對象 axios.interceptors.response.use(function (data) { data.data = data.data + ' - modified by interceptor'; return data; });
在 lib/axios.js
路徑下,咱們能夠找到 axios 對象的定義。爲了能直觀地瞭解對象之間的關係,阿寶哥建議你們在讀源碼的過程當中,多動手畫畫圖。好比阿寶哥使用下圖來總結一下 Axios
對象與 InterceptorManager
對象的內部結構與關係:
如今咱們已經知道如何註冊攔截器任務,但僅僅註冊任務是不夠,咱們還須要對已註冊的任務進行編排,這樣才能確保任務的執行順序。
一樣對於任務編排,也可使用圖的形式來展示任務編排後的結果。 這裏有一個小技巧,就是能夠採用對比的形式來展現任務編排後的結果,這樣子會更加清楚任務編排的處理邏輯。
任務編排完成後,要發起 HTTP 請求,咱們還須要按編排後的順序執行任務調度。
須要注意的是:在閱讀源碼過程當中,不要太在乎細節。好比在研究 Axios 攔截器原理時,不須要再深刻了解 dispatchRequest 背後的具體實現,只需知道該方法用於實現發送 HTTP 請求便可,這樣纔不會把整個線路拉得太長。
在分析完特定的功能點以後,也許你已經讀懂的具體的源代碼。但阿寶哥以爲這並非最重要的,更重要的是思考它的設計思想,這樣設計有什麼好處,對於咱們有沒有什麼值得借鑑和學習的地方。好比參考 Axios 攔截器的設計模型,咱們就能夠抽出如下通用的任務處理模型:
上面阿寶哥以 Axios 的攔截器爲例,分享了讀 Axios 源碼的思路與技巧。接下來阿寶哥來分享一些讀源碼的建議和輔助工具。
若是你對下列輔助工具感興趣的話,能夠經過如下圖片來源的連接,來直接打開每一個工具的在線地址。
(圖片來源:https://www.processon.com/vie...)
其實除了上面的內容以外,讀優秀開源項目還有挺多值得關注的地方。阿寶哥在學習 BetterScroll 項目源碼時,總結了一張思惟導圖:
(圖片來源:https://www.processon.com/vie...)
下面阿寶哥用一張圖來總結一下 axios 和 better-scroll 這兩個開源項目的學習路線:
一、Axios 項目的切入點是從 Github 中的功能特性中篩選出來的;二、BetterScroll 的切入點是從掘金上 BetterScroll 2.0 發佈:精益求精,與你同行 這篇文章中介紹的功能亮點中找到的。
除此以外,阿寶哥也來簡單總結一下本文介紹的讀源碼的思路與技巧:
本文阿寶哥分享了我的讀源碼的思路、技巧與工具,但願閱讀完本文能對你有所啓發或幫助。若是你有讀源碼更好的思路與技巧,歡迎隨時跟阿寶哥交流哈。有寫得很差的地方,也請各位見諒哈。