axios源码中的10多个工具函数,值得一学~

大家好,我是若川。最近组织了源码共读活动,感兴趣的可以点此加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。

本文来自读者Ethan01投稿,写了axios源码中的工具函数~非常值得一学。原文链接:https://juejin.cn/post/7042610679815241758

1.前言

歌德说过:读一本好书,就是在和高尚的人谈话。

同理,读优秀的开源项目的源码,就是在和牛逼的大佬交流。

之前总觉得阅读源码是一件了不起的事情,是只有大佬才会去做的事。其实源码也不是想象的那么难,至少有很多看得懂。 比如源码中的工具函数,就算是初级的前端开发也是能够看懂的。重要的是,要迈出这一步,阅读源码没什么的。

阅读本文,你将学到:

1、javascript、nodejs调试技巧及调试工具;
2、如何学习调试axios源码;
3、如何学习优秀开源项目的代码,应用到自己的项目;
4、axios源码中实用的工具函数;

2.环境准备

2.1 读开源项目的贡献指南

打开 axios[1] , 你会惊奇的发现,这不是在浏览器中打开了一个vscode吗?你没有看错,确实是在浏览器中打开了vscode,而且还打开了axios的源码。如果你仔细看了浏览器地址栏里的url, 你会发现github后多了1s,顾名思义,就是1s打开github上的项目。一个小扩展:在每一个github项目中的url里直接加上1s,就能在网页版vscode中查看源码了(不过貌似现在只能查看,不能调试,调试的话还是要把源码clone到本地)。

开源项目一般能在根目录下的README.md文件或CONTRIBUTING.md中找到贡献指南。贡献指南中说明了参与贡献代码的一些注意事项,比如:代码风格、代码提交注释格式、开发、调试等。

打开CONTRIBUTING.md[2],可以看到在54行的内容:

Running sandbox in browser```bash
$ npm start
# Open 127.0.0.1:3000

这里就是告诉我们在如何在浏览器中运行项目的。

2.2 克隆项目并运行

这里使用axios的版本是v0.24.0;

git clone https://github.com/axios/axios.gitcd axiosnpm start打开 http://localhost:3000/

这时候可以看到这么一个页面:

6406c80fdbdb46ac3db4a30410930dde.png
image.png

打开浏览器的控制台,选中source选项,然后在axios目录中可以找到源码,如下图:

29bb3311799b37771e551eacac913aa7.png
image.png

这个axios.js就是入口文件,这时候就可以随意打断点进行调试了。

其实,阅读所有源码的流程都类似,之所以说的这么详细,是为了能够让没有阅读过源码的同学也能够跟着一步一步的阅读起来。当你读完之后,肯定会有不少的收获,把这个过程和收获记录下来,慢慢的提升自己,早晚会成为大佬。

3. 工具函数

今天的主角是`utils.js`[3]文件, 以下列出了文件中的工具函数:

3.1 isArray 判断数组

var toString = Object.prototype.toString;// 可以通过 `toString()` 来获取每个对象的类型
// 一般返回值是 Boolean 类型的函数,命名都以 is 开头
function isArray(val) {return toString.call(val) === '[object Array]';
}

3.2 isUndefined 判断Undefined

// 直接用`typeof`判断
// 注意 typeof null === 'object'
function isUndefined(val) {return typeof val === 'undefined';
}

3.3 isBuffer 判断 buffer

// 先判断不是 `undefined`和`null`
// 再判断 `val`存在构造函数,因为`Buffer`本身是一个类
// 最后通过自身的`isBuffer`方法判断function isBuffer(val) {return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor)&& typeof val.constructor.isBuffer === 'function' && val.constructor.isBuffer(val);
}

什么是Buffer?

JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。

但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。详细可以看 官方文档[4] 或 更通俗易懂的解释[5]

因为axios可以运行在浏览器和node环境中,所以内部会用到nodejs相关的知识。

3.4 isFormData 判断FormData

// `instanceof` 运算符用于检测构造函数的 `prototype` 属性是否出现在某个实例对象的原型链上function isFormData(val) {return (typeof FormData !== 'undefined') && (val instanceof FormData);
}// instanceof 用法function C() {}
function D() {}const c = new C()c instanceof C // output: true   因为 Object.getPrototypeOf(c) === C.prototypec instanceof Object // output: true   因为 Object.prototype.isPrototypeOf(c)c instanceof D // output: false   因为 D.prototype 不在 c 的原型链上

3.5 isObject 判断对象

// 排除 `null`的情况
function isObject(val) {return val !== null && typeof val === 'object';
}

3.6 isPlainObject 判断 纯对象

纯对象:用{}new Object()创建的对象。

function isPlainObject(val) {if (Object.prototype.toString.call(val) !== '[object Object]') {return false;}var prototype = Object.getPrototypeOf(val);return prototype === null || prototype === Object.prototype;
}// 例子1
const o = {name: 'jay}
isPlainObject(o) // true// 例子2
const o = new Object()
o.name = 'jay'
isPlainObject(o)   // true// 例子3
function C() {}
const c = new C()
isPlainObject(c);  // false// 其实就是判断目标对象的原型是不是`null` 或 `Object.prototype`

3.7 isDate 判断Date

function isDate(val) {return Object.prototype.toString.call(val) === '[object Date]';
}

3.8 isFile 判断文件类型

function isFile(val) {return Object.prototype.toString.call(val) === '[object File]';
}

3.9 isBlob 判断Blob

function isBlob(val) {return Object.prototype.toString.call(val) === '[object Blob]';
}

Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取。

3.10 isFunction 判断函数

function isFunction(val) {return Object.prototype.toString.call(val) === '[object Function]';
}

3.11 isStream 判断是否是流

// 这里`isObject`、`isFunction`为上文提到的方法
function isStream(val) {return isObject(val) && isFunction(val.pipe);
}

3.12 isURLSearchParams 判断URLSearchParams

function isURLSearchParams(val) {return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams;
}// 例子
const paramsString = "q=URLUtils.searchParams&topic=api"
const searchParams = new URLSearchParams(paramsString);
isURLSearchParams(searchParams) // true

URLSearchParams 接口定义了一些实用的方法来处理 URL 的查询字符串,详情可看 MDN[6]

var paramsString = "q=URLUtils.searchParams&topic=api"
var searchParams = new URLSearchParams(paramsString);for (let p of searchParams) {console.log(p);
}// 输出 
[ 'q', 'URLUtils.searchParams' ]
[ 'topic', 'api' ]searchParams.has("topic") === true; // true
searchParams.get("topic") === "api"; // true
searchParams.getAll("topic"); // ["api"]
searchParams.get("foo") === null; // true
searchParams.append("topic", "webdev");
searchParams.toString(); // "q=URLUtils.searchParams&topic=api&topic=webdev"
searchParams.set("topic", "More webdev");
searchParams.toString(); // "q=URLUtils.searchParams&topic=More+webdev"
searchParams.delete("topic");
searchParams.toString(); // "q=URLUtils.searchParams"

3.13 trim 去除首尾空格

// `trim`方法不存在的话,用正则
function trim(str) {return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '');
}

3.14 isStandardBrowserEnv 判断标准浏览器环境

function isStandardBrowserEnv() {if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative' ||navigator.product === 'NativeScript' ||navigator.product === 'NS')) {return false;}return (typeof window !== 'undefined' &&typeof document !== 'undefined');
}

但是官方已经不推荐使用这个属性navigator.product

316699b6b380f2566226db93bf6a9818.png
image.png

3.15 forEach 遍历对象或数组

保留了英文注释,提升大家的英文阅读能力。

/*** Iterate over an Array or an Object invoking a function for each item.*  用一个函数去迭代数组或对象** If `obj` is an Array callback will be called passing* the value, index, and complete array for each item.* 如果是数组,回调将会调用value, index, 和整个数组** If 'obj' is an Object callback will be called passing* the value, key, and complete object for each property.* 如果是对象,回调将会调用value, key, 和整个对象** @param {Object|Array} obj The object to iterate* @param {Function} fn The callback to invoke for each item*/function forEach(obj, fn) {// Don't bother if no value provided// 如果值不存在,无需处理if (obj === null || typeof obj === 'undefined') {return;}// Force an array if not already something iterable// 如果不是对象类型,强制转成数组类型if (typeof obj !== 'object') {obj = [obj];}if (isArray(obj)) {// Iterate over array values// 是数组,for循环执行回调fnfor (var i = 0, l = obj.length; i < l; i++) {fn.call(null, obj[i], i, obj);}} else {// Iterate over object keys// 是对象,for循环执行回调fnfor (var key in obj) {// 只遍历可枚举属性if (Object.prototype.hasOwnProperty.call(obj, key)) {fn.call(null, obj[key], key, obj);}}}
}

所以,源码为什么不用forEachfor...in...呢???????

3.16 stripBOM删除UTF-8编码中BOM

/*** Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)** @param {string} content with BOM* @return {string} content value without BOM*/function stripBOM(content) {if (content.charCodeAt(0) === 0xFEFF) {content = content.slice(1);}return content;
}

所谓 BOM,全称是Byte Order Mark,它是一个Unicode字符,通常出现在文本的开头,用来标识字节序。UTF-8主要的优点是可以兼容ASCII,但如果使用BOM的话,这个好处就荡然无存了。

4.总结

本文主要介绍了axios源码的调试过程,以及介绍了一些utils.js中的非常实用的工具函数;相信通过阅读源码,日积月累,并把这些代码或思想应用的自己项目中去,相信能够很好的提升自己的编码能力。

come on! worker!

同时也推荐一些好用的工具:

浏览器中运行`vscode`, 查看源码[7]

代码沙盒,能运行多种语言,且可以添加依赖[8]

vs code 的 code Runner插件[9]

参考资料

[1]

axios: https://github1s.com/axios/axios

[2]

CONTRIBUTING.md: https://github1s.com/axios/axios/blob/HEAD/CONTRIBUTING.md

[3]

utils.js: https://github.com/axios/axios/blob/master/lib/utils.js

[4]

官方文档: http://nodejs.cn/api/buffer.html#buffer

[5]

更通俗易懂的解释: https://www.runoob.com/nodejs/nodejs-buffer.html

[6]

MDN: https://developer.mozilla.org/zh-CN/docs/Web/API/URLSearchParams

[7]

浏览器中运行vscode, 查看源码: https://github1s.com/axios/axios

[8]

代码沙盒,能运行多种语言,且可以添加依赖: https://codesandbox.io/

[9]

vs code 的 code Runner插件: https://marketplace.visualstudio.com/items?itemName=formulahendry.code-runner


0686776708c31ed9609ec51dad113a54.gif

················· 若川简介 ·················

你好,我是若川,毕业于江西高校。现在是一名前端开发“工程师”。写有《学习源码整体架构系列》20余篇,在知乎、掘金收获超百万阅读。
从2014年起,每年都会写一篇年度总结,已经写了7篇,点击查看年度总结。
同时,最近组织了源码共读活动,帮助3000+前端人学会看源码。公众号愿景:帮助5年内前端人走向前列。

133214fd2211e649fd3de1de4e6f1020.png

识别方二维码加我微信、拉你进源码共读

今日话题

略。分享、收藏、点赞、在看我的文章就是对我最大的支持~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/275078.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

寄充气娃娃怎么寄_我如何在5小时内寄出新设计作品集

寄充气娃娃怎么寄Over the Easter break, I challenged myself to set aside an evening rethinking the structure, content and design of my portfolio in Notion with a focus on its 在复活节假期&#xff0c;我挑战自己&#xff0c;把一个晚上放在一边&#xff0c;重新思…

最全 JavaScript Array 方法 详解

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。我们在日常开发中&#…

管理沟通中移情的应用_移情在设计中的重要性

管理沟通中移情的应用One of the most important aspects of any great design is the empathetic understanding of and connection to the user. If a design is ‘selfish’, as in when a product designed with the designer in mind and not the user, it will ultimatel…

网易前端进阶特训营,邀你免费入营!一举解决面试晋升难题!

网易等大厂的前端岗位一直紧缺&#xff0c;特别是资深级。最近一位小哥面进网易&#xff0c;定级P4&#xff08;资深&#xff09;&#xff0c;总包60W&#xff0c;给大家带来真实面经要点分享。网易的要求有&#xff1a;1.对性能优化有较好理解&#xff0c;熟悉常用调试工具2.熟…

angelica类似_亲爱的当归(Angelica)是第一个让我哭泣的VR体验

angelica类似It was a night just like any other night. I finished work for the day and closed my laptop. I had dinner and after an hour, I put on my Oculus Quest headset in order to begin my VR workout.就像其他任何夜晚一样&#xff0c; 这 是一个夜晚。 我完成…

面试官:请手写一个带取消功能的延迟函数,axios 取消功能的原理是什么

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。本文仓库 https://githu…

facebook 面试_如何为您的Facebook产品设计面试做准备

facebook 面试重点 (Top highlight)Last month, I joined Facebook to work on Instagram DMs and as a way to pay it forward, I 上个月&#xff0c;我加入了Facebook&#xff0c;从事Instagram DM的工作&#xff0c;作为一种支付方式&#xff0c;我 offered to help anyone…

8年了,开始写点东西了

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。今天分享一位大佬的文章…

荒径 弗罗斯特_弗罗斯特庞克,颠覆性城市建设者

荒径 弗罗斯特Most gamers are familiar with Will Wright’s famous SimCity series. It created the city building genre and there have been many attempts over the years to ape it. But few developers have been bold enough to completely deconstruct the formula; …

Gitee 如何自动部署博客 Pages?推荐用这个GitHub Actions!

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。前段时间我把自己的博客…

现在流行的画原型图工具_原型资源图:8种流行原型工具的综合指南

现在流行的画原型图工具Although tools are not the most important things to learn as a UX designer, inevitably you need to use it in order to achieve your more important goals, to solve user’s problems. This article covers today’s 8 popular UX prototyping …

持续5个月,200+笔记,3千多人参与,邀请你来学源码~

注意&#xff1a;本文点击文末阅读原文可查看文中所有链接。我正在参加掘金年度人气作者投票活动&#xff0c;大家有空可以加微信群帮忙投票&#xff0c;感谢大家&#xff01;想起今天还没发文&#xff0c;就开放下微信群二维码&#xff0c;大家扫码进群读源码和帮忙投票吧。群…

第2年,倒数第3天,1.5万票,感动!

1源码共读大家好&#xff0c;我是若川。众所周知。从8月份开始&#xff0c;我组织了源码共读活动&#xff0c;至今已经有5个月了&#xff0c;每周一期&#xff0c;进行到了第18期。每周坚持写源码解读文章&#xff0c;每天坚持答疑解惑&#xff0c;帮助了很多人学会看源码&…

启发式搜索给神经网络_神经科学如何支持UX启发式

启发式搜索给神经网络重点 (Top highlight)Interaction and UX designers have long known and used heuristics to guide the creation of a user-friendly interface. We know empirically that these principles work, and they make “common sense”. These heuristics th…

Django实战(1):需求分析和设计

Depot是《Agile Web Development with Rails》中的一个购物车应用。 该书中用多次迭代的方法&#xff0c;逐步实现购物车应用&#xff0c;使很多人走上了rails开发的道路。 遗憾的是Django世界中好像没有类似的指引&#xff0c;也许是因为pythoner 不需要具体的例子。 但是如果…

海浪 shader_海浪下的发现

海浪 shaderI’ve been playing Subnautica for over 25 hours now, and likely have at least that many more to go. The game puts you in the shoes of a crew member on the Aurora, a spaceship that suffers a catastrophic incident and plummets to the largely ocean…

最后一天,特邀小姐姐配音拉票,今日可投28票

1源码共读大家好&#xff0c;我是若川。最后一天&#xff0c;特邀小姐姐配音拉票&#xff0c;超级好听。众所周知。从8月份开始&#xff0c;我组织了源码共读活动&#xff0c;至今已经有5个月了&#xff0c;每周一期&#xff0c;进行到了第18期。每周坚持写源码解读文章&#x…

对数据可视化的理解_使数据可视化更容易理解

对数据可视化的理解Data is weaving its way into almost all aspects of our lives since the past decade. Our ability to store more information in smaller and smaller spaces has encouraged us to make sure we leave no information out. The ease of collecting inf…

面试官:项目中常用的 .env 文件原理是什么?如何实现?

1. 前言大家好&#xff0c;我是若川。持续组织了5个月源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。本文仓库 h…

梯度下降法和随机梯度下降法

1. 梯度 在微积分里面&#xff0c;对多元函数的参数求∂偏导数&#xff0c;把求得的各个参数的偏导数以向量的形式写出来&#xff0c;就是梯度。比如函数f(x,y), 分别对x,y求偏导数&#xff0c;求得的梯度向量就是(∂f/∂x, ∂f/∂y)T,简称grad f(x,y)或者▽f(x,y)。对于在点(x…