axios 工具函数
1.前言
本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
有了输入,我们才有可能会有输出,所以,我开始学习源码了。然而,学习源码也不是那么简单的事情。千里之行,始于足下。在此特别感谢川哥。
2.环境准备
axios是我们在工作中,请求参数的一个库。今天来阅读他的工具函数源码。我阅读的是0.27.2的工具库源码。首先我们先把他的源码拉下来在GitHub上,我们把他git clone下来。放在本地我们把他运行起来。
git clone https://github.com/axios/axios/tree/v0.27.2
npm install
npm start
执行完上面的命令,你会看到如下界面。
3.有请主角—工具函数
如上图所示,工具函数在lib/untils.js文件里面.
3.1判断数据类型,你只要用了这个函数,他就会把你的用过的缓存起来。
const { toString } = Object.prototype;
const kindOf = (cache => thing => {
const str = toString.call(thing);
return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase());
})(Object.create(null));
console.log(kindOf(1)) //number
console.log(kindOf("abc")) //string
console.log(kindOf(()=>{})) //function
console.log(kindOf(undefined)) //undefined
console.log(kindOf(null)) //null
console.log(kindOf({})) //object
3.2判断一个数据是不是某种复杂类型
const kindOfTest = (type) => {
type = type.toLowerCase();
return (thing) => kindOf(thing) === type
}
console.log(kindOfTest('Date')(new Date("2012-2-5")))
3.3判断一个变量的基本数据类型,主要判断了undefined,字符串,函数,数字类型。
const typeOfTest = type => thing => typeof thing === type;
//是否是undefined
const isUndefined = typeOfTest('undefined');
console.log(isUndefined(undefined)) // true
//是否是字符串类型
const isString = typeOfTest('string');
console.log(isString("1314520")) // true
//是否是函数
const isFunction = typeOfTest('function');
console.log(isFunction(()=>{})) // true
//是否是一个数字
const isNumber = typeOfTest('number');
console.log(isNumber(123))
3.4判断是否是一个对象
const isObject = (thing) => thing !== null && typeof thing === 'object';
var obj = new Object(null)
console.log(isObject(obj)) // true
3.5判断一个值是否为buffer 很少用在前端里面
function isBuffer(val) {
return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor)
&& isFunction(val.constructor.isBuffer) && val.constructor.isBuffer(val);
}
3.6判断一个值是否是Boolean类型
const isBoolean = thing => thing === true || thing === false;
var flag = true;
console.log(isBoolean(flag))
3.7判断一个值是不是纯对象。
const {getPrototypeOf} = Object;
const isPlainObject = (val) => {
if (kindOf(val) !== 'object') {
return false;
}
//getPrototypeOf 要返回其原型的对象。
const prototype = getPrototypeOf(val);
return prototype === null || prototype === Object.prototype;
}
3.8判断一个值是否是日期对象
const isDate = kindOfTest('Date');
console.log(isDate(new Date("2022-5-6")))
3.9判断一个值是否为file类型
const isFile = kindOfTest('File');
3.10判断一个值是否为Blob类型
const isBlob = kindOfTest('Blob');
console.log(isBlob(new Blob()))
3.11判断一个值是否为FileList
const isFileList = kindOfTest('FileList');
3.12判断一个值是不是stream
const isStream = (val) => isObject(val) && isFunction(val.pipe);
3.13判断一个值是不是FormData
const isFormData = (thing) => {
const pattern = '[object FormData]';
return thing && (
(typeof FormData === 'function' && thing instanceof FormData) ||
toString.call(thing) === pattern ||
(isFunction(thing.toString) && thing.toString() === pattern)
);
}
console.log(isFormData(new FormData())) // true
3.14去除字符串开头和结尾的空格
const trim = (str) => str.trim ?
str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
3.15永远返回空的函数
const noop = () => {}
3.16检测一个数是不是一个有穷数
const toFiniteNumber = (value, defaultValue) => {
value = +value;
return Number.isFinite(value) ? value : defaultValue;
}
console.log(toFiniteNumber(1,2))
3.17数组的forEach方法,传入一个对象,一个函数即可调用,主要分为数组和对象的遍历。
const {isArray} = Array;
function forEach(obj, fn, {allOwnKeys = false} = {}) {
//如果没有传值就返回
if (obj === null || typeof obj === 'undefined') {
return;
}
let i;
let l;
//如果不是一个可迭代的对象就强制使用数组
if (typeof obj !== 'object') {
/*eslint no-param-reassign:0*/
obj = [obj];
}
if (isArray(obj)) {
// Iterate over array values
for (i = 0, l = obj.length; i < l; i++) {
fn.call(null, obj[i], i, obj);
}
} else {
// Iterate over object keys
const keys = allOwnKeys ? Object.getOwnPropertyNames(obj) : Object.keys(obj);
const len = keys.length;
let key;
for (i = 0; i < len; i++) {
key = keys[i];
fn.call(null, obj[key], key, obj);
}
}
}
3.18把一个字符串化为数组
const toArray = (thing) => {
if (!thing) return null;
if (isArray(thing)) return thing;
let i = thing.length;
if (!isNumber(i)) return null;
const arr = new Array(i);
while (i-- > 0) {
arr[i] = thing[i];
}
return arr;
}
console.log(toArray("123")) // ['1', '2', '3']
3.19确定字符串是否以指定字符串的字符结尾
const endsWith = (str, searchString, position) => {
str = String(str);
if (position === undefined || position > str.length) {
position = str.length;
}
position -= searchString.length;
const lastIndex = str.indexOf(searchString, position);
return lastIndex !== -1 && lastIndex === position;
}
console.log(endsWith("123456","1",1)) // true
大概会遇到的问题:
当你在克隆完项目,安装完依赖后,你会遇到__dirname is not found。这样的类似的报错。因为diename是cjs下面的一个全局变量,而现在的是环境是ESM。加入下面两句代码就可以了。
const __filename = url.fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
这是源码共读的第19期,链接:juejin.cn/post/708311…