近期阿宝哥在团队内搞了一个 如何读源码 的专题,主要目的是让团队的小伙伴们了解读源码的思路与技巧。在此期间,阿宝哥也写了 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 发布:精益求精,与你同行 这篇文章中介绍的功能亮点中找到的。
除此以外,阿宝哥也来简单总结一下本文介绍的读源码的思路与技巧:
本文阿宝哥分享了我的读源码的思路、技巧与工具,但愿阅读完本文能对你有所启发或帮助。若是你有读源码更好的思路与技巧,欢迎随时跟阿宝哥交流哈。有写得很差的地方,也请各位见谅哈。