持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情
前言
axios是前端主流的http库,基于promise,可以用在浏览器和node.js中使用,本文从源码角度分析一下axios,可以让我们更好的理解和使用它。
axios的特性
- 从浏览器中创建 XMLHttpRequests
- 从 node.js 创建 http 请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求数据和响应数据
- 取消请求
- 自动转换 JSON 数据
- 客户端支持防御 XSRF
示例
这里我们创建一个请求,路径是/user/,传了id为12345,并且写了异步获取响应和捕获错误的方法,写法很像promise
// 为给定 ID 的 user 创建请求
axios.get('/user?ID=12345')
.then(function (response) { // 返回响应
console.log(response);
})
.catch(function (error) { // 捕获错误
console.log(error);
});
目录分析
我们把项目拉下来,目录如上图,可以看到所有的主文件都在lib文件夹中,其他的都是一些示例、打包后、配置文件等。
我们把文件/文件/名翻译一下:
- adapters/ --> 适配器
- cancel/ --> 取消
- core/ --> 核心
- default/ --> 默认
- env/ --> 环境
- helpers/ --> 帮手
- platform/ --> 平台
- axios.js --> 以axios命名的应该是对外的主入口
- utils.js --> 工具库
axios.js
开启严格模式
'use strict';
引入axios核心文件及一些工具
var utils = require('./utils'); // 工具
var bind = require('./helpers/bind'); // 绑定函数
var Axios = require('./core/Axios'); // axios主文件
var mergeConfig = require('./core/mergeConfig'); // 合并配置
var defaults = require('./defaults'); // 默认配置文件
var formDataToJSON = require('./helpers/formDataToJSON'); // formData表单转成JSON方法
定义创建实例的函数
- 创建了一个
Axios的实例,并且赋值给context变量 - 暂时先忽略bind方法,暂时当绑定作用用,这里可以看到,Axios的原型方法
request绑定了刚才创建的context变量(Axios实例),这里返回了一个新的实例给instance变量 - 接下来通过
utils.extend方法(让第三个属性继承前两个参数的属性),我们复制了第二次的实例和新的Axios原型对象的实例到第一次定义的实例上 - 接下来把第一次的属性(
context)再复制给第二次的实例上(instance) - 给第二次创建的实例定义了
create方法,调用这个方法需要传配置参数,返回的值是该创建实例的方法,这一步用于创建实例的工厂 - 最后返回第二次创建的实例
function createInstance(defaultConfig) {
var context = new Axios(defaultConfig);
var instance = bind(Axios.prototype.request, context);
// Copy axios.prototype to instance
utils.extend(instance, Axios.prototype, context);
// Copy context to instance
utils.extend(instance, context);
// Factory for creating new instances
instance.create = function create(instanceConfig) {
return createInstance(mergeConfig(defaultConfig, instanceConfig));
};
return instance;
}
把默认参数传过去,创建axios实例并且给它增加了一些属性方法,尤其注意axios.Axios = Axios,这一步的目的是公开Axios类以允许类继承。
// Create the default instance to be exported
var axios = createInstance(defaults);
// Expose Axios class to allow class inheritance
axios.Axios = Axios;
// Expose Cancel & CancelToken
axios.CanceledError = require('./cancel/CanceledError');
axios.CancelToken = require('./cancel/CancelToken');
axios.isCancel = require('./cancel/isCancel');
axios.VERSION = require('./env/data').version;
axios.toFormData = require('./helpers/toFormData');
// Expose AxiosError class
axios.AxiosError = require('../lib/core/AxiosError');
// alias for CanceledError for backward compatibility
axios.Cancel = axios.CanceledError;
// Expose all/spread
axios.all = function all(promises) {
return Promise.all(promises);
};
axios.spread = require('./helpers/spread');
// Expose isAxiosError
axios.isAxiosError = require('./helpers/isAxiosError');
axios.formToJSON = function(thing) {
return formDataToJSON(utils.isHTMLForm(thing) ? new FormData(thing) : thing);
};
既然是主文件,肯定需要导出方法:
module.exports = axios;
// Allow use of default import syntax in TypeScript
module.exports.default = axios;
结语
本文介绍了什么是axios及axios的特性,讲了下lib文件的各个子目录的作用,对axios.js进行了逐行解析,这个文件是我们外部引用时使用的主入口,该文件创建了一个实例,并且绑定了一些方法,多处地方都是用了原型,这里需要特别注意。