【axios源码】- 过渡选项校验函数validator研读解析

首发于我的公众号「前端面壁者」,欢迎关注。

transitional options for backward compatibility that may be removed in the newer versions

Validator81行代码,在发送请求时会检测axios版本以便作一些兼容性配置

一、环境准备

  • axios 版本 v0.24.0

  • 通过 github1s 网页可以 查看 axios 源码

  • 调试需要 clone 到本地

git clone https://github.com/axios/axios.git

cd axios

npm start

http://localhost:3000/

二、函数研读

transitional options for backward compatibility that may be removed in the newer versions

可在较新版本中删除的向后兼容性过渡选项

1. 调用场景

在核心库函core-Axios函数中有以下调用代码段

var transitional = config.transitional;

if (transitional !== undefined) {
    validator.assertOptions(
        transitional,
        {
            silentJSONParsing: validators.transitional(validators.boolean),
            forcedJSONParsing: validators.transitional(validators.boolean),
            clarifyTimeoutError: validators.transitional(validators.boolean),
        },
        false
    );
}
  • 使用validator模块的assertOptions函数将transitional中的值初始化过渡属性配置项[silentJSONParsingforcedJSONParsingclarifyTimeoutError]
  • 这里重点关注初始化数据来源transitional,来自axios-defaults中的配置与自定义配置的合并,参见core-axios line-43与[lib-axios line-34]。但我们知道axios 请求配置并不支持自定义配置这三个配置项,所以这些工作对开发者是个黑盒,并不可见,往往也是造成我们开发困惑的原因
配置项作用
[transitional-silentJSONParsing]版本兼容配置-返回值转换为 Json 出错时是否置为 null 返回
[transitional-forcedJSONParsing]版本兼容配置-responseType 设置非 json 类型时是否强制转换成 json 格式
[transitional-clarifyTimeoutError]版本兼容配置-请求超时时是否默认返回 ETIMEDOUT 类型错

Tips: 更多内容可以参考上一篇文章axios-defaults 源码构造对象 defaults这一节三种过渡属性的使用场景

Tips: 从v0.22.0版本已经废弃,可参见githubaxios - Release/v0.22.0

image.png

2. 正文

【2.1】获取版本号

var VERSION = require('../env/data').version;

===>
module.exports = {
  "version": "0.24.0"
};
  • 首先会去 env 下读取当前的axios版本号,这里的version是固定的,取决于我们下载的 axios 版本

【2.2】类型校验器对象

var validators = {};

// eslint-disable-next-line func-names
["object", "boolean", "number", "function", "string", "symbol"].forEach(
    function (type, i) {
        validators[type] = function validator(thing) {
            return typeof thing === type || "a" + (i < 1 ? "n " : " ") + type;
        };
    }
);

validator.png

  • 分别用object, boolean, number, function, string, symbol作为键初始化对象validators,键值为validator函数被调用时的返回值
  • validator函数的返回值为Boolean类型或String类型,这取决于入参thing,当thing与当前键type表示的类型相等时返回true,否则返回一个字符串a ${type}an ${type}表示当前键type的类型

Tips: func-names规则可以强制或禁止使用命名函数表达式

【2.3】内部函数 transitional

/**
 * Transitional option validator
 * @param {function|boolean?} validator - set to false if the transitional option has been removed
 * @param {string?} version - deprecated version / removed since version
 * @param {string?} message - some message with additional info
 * @returns {function}
 */
validators.transitional = function transitional(validator, version, message) {
  function formatMessage(opt, desc) {
    return '[Axios v' + VERSION + '] Transitional option \'' + opt + '\'' + desc + (message ? '. ' + message : '');
  }

  // eslint-disable-next-line func-names
  return function(value, opt, opts) {
    if (validator === false) {
      throw new Error(formatMessage(opt, ' has been removed' + (version ? ' in ' + version : '')));
    }

    if (version && !deprecatedWarnings[opt]) {
      deprecatedWarnings[opt] = true;
      // eslint-disable-next-line no-console
      console.warn(
        formatMessage(
          opt,
          ' has been deprecated since v' + version + ' and will be removed in the near future'
        )
      );
    }

    return validator ? validator(value, opt, opts) : true;
  };
};
  • 过渡选项配置校验函数,挂载在validators上,提醒用户旧版本的[silentJSONParsingforcedJSONParsingclarifyTimeoutError]选项将被遗弃
  • 入参为validator, version, message,从前文知从v0.22.0版本过渡配置选项已经废弃,这里的versionmessage都是空
  • validator为false时,当开发者试图配置过渡属性[silentJSONParsingforcedJSONParsingclarifyTimeoutError]时始终会抛出Error而不是在控制台输出warn,因此达到了过渡的功能🐶,同时始终返回true给assertOptions从而continue进入下一配置选项的断言
  • validator为true时,会返回当前类型校验器validator函数的返回值

【2.4】内部函数 assertOptions

/**
 * Assert object's properties type
 * @param {object} options
 * @param {object} schema
 * @param {boolean?} allowUnknown
 */

function assertOptions(options, schema, allowUnknown) {
  if (typeof options !== 'object') {
    throw new TypeError('options must be an object');
  }
  var keys = Object.keys(options);
  var i = keys.length;
  while (i-- > 0) {
    var opt = keys[i];
    var validator = schema[opt];   // validator = validators.transitional(validators.boolean)
    if (validator) {
      var value = options[opt]; // Boolean
      var result = value === undefined || validator(value, opt, options);
      if (result !== true) {
        throw new TypeError('option ' + opt + ' must be ' + result);
      }
      continue;
    }
    if (allowUnknown !== true) {
      throw Error('Unknown option ' + opt);
    }
  }
}
  • 版本断言函数
  • 配置项options必须是object否则抛出类型错
  • 当禁止开发者配置过渡属性时入参options只能来自axios-defaults中的构造对象 defaults默认配置[silentJSONParsing: true, forcedJSONParsing: true, clarifyTimeoutError: false]
  • validatorvalidators.boolean
  • allowUnknown配置当opt类型不属于过渡配置选项三者之一时是否会直接抛出错误

【2.5】导出

module.exports = {
  assertOptions: assertOptions,
  validators: validators
};
  • 模块化方式导出validators对象和assertOptions函数

三、参考

1. 的文章【axios源码】- 实例化配置函数defaults研读解析

2. 林景宜的记事本 - Axios源码解析(二):通用工具方法

3. 仙凌阁 - 详细Axios源码解读

4. MDN

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值