你不知道的axios工具函数

106 阅读3分钟

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

执行完上面的命令,你会看到如下界面。

1.png

3.有请主角—工具函数

2.png

如上图所示,工具函数在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…