1.axios是什么?有什么优点?用法?
axios 是通过 Promise 实现对 ajax 技术的一种封装,在浏览器使用原生 XHR 对象,在node使用 http 模块
axios优点:
- 从浏览器中创建 XMLHttpRequest
- 从 node.js 创建 http 请求
- 支持 Promise API
- 转换请求和响应数据
- 支持请求/响应拦截器
- 自动转换JSON数据
axios 既可以当函数调用,也可以当对象使用 ( axios({}) axios.get() )
-
请求方法的别名
axios(config) (通用/最本质的发任意类型请求的方式)
axios(url[, config]) (可以只指定url发get请求)
axios.request(config) (等同于 axios(config) )
axios.get(url[, config]) (发get请求)
axios.post(url[, data[, config]]) (发post请求)
axios.put(url[, data[, config]]) (发put请求)
axios.delete(url[, config]) (发delete请求)
axios.head(url[, config])
axios.patch(url[, data[, config]]) -
拦截器
axios.defaults.xxx (请求的默认全局配置)
axios.interceptors.request.use() (添加请求拦截器)
axios.interceptors.response.use() (添加响应拦截器) -
创建实例和一些取消请求方法
axios.create([config]) (创建一个新的axios实例 注意:它没有下面的功能)
axios.all(iterable) (用于批量执行多个异步请求)
axios.spread(callback) (用来指定接收所有成功数据的回调函数的方法)
axios.Cancel() (用于创建取消请求的错误对象)
axios.isCancel() (是否是一个取消请求的错误)
axios.CancelToken() (用于创建取消请求的token对象)
2.axios源码解析
- cancel (定义取消功能)
- core
Axios.js (axios的核心主类)
dispatchRequest.js (用来调用http请求适配器方法发送请求)
InterceptorManager.js (拦截器构造函数)
settle.js (根据http响应状态,改变Promise的状态) - helpers (一些辅助方法)
- adapters
http.js (实现http适配器)
xhr.js (实现xhr适配器) - axios.js (对外暴露接口)
- defaults.js (默认配置)
- utils.js (公用工具)
axios.js文件,创建实例对象,对外暴露出去
- 创建 Axios 实例 context,并且将默认配置传入
- 创建一个 instance 返回的是一个 wrap 函数,该函数传入Axios.prototype.request方法和context实例对象
- 所以 axios() = instance() = wrap() = Axios.prototype.request.call(context)
- 然后使用 extend 方法,将 Axios.prototype 上的属性方法拷贝 instance
- 所以 axios.get() = instace.get = Axios.prototype.get() 在给方法中 return this.request(),所以最后axios.get() = Axios.prototype.request() 还是调用了这个方法
- 最后将 context 实例对象拷贝给 instance
// axios.ja 入口文件
var Axios = require('./core/Axios');
var defaults = require('./defaults');
function createInstance(defaultConfig) {
// 创建 axios 实例
var context = new Axios(defaultConfig);
// bind返回wrap方法,而不是axios实例
var instance = bind(Axios.prototype.request, context);
// extend 将 Axios.prototype 拷贝给 instance
// axios = Axios.prototype => axios.get = Axios.prototype.get
// 这也是为什么可以使用 axios.get
utils.extend(instance, Axios.prototype, context);
utils.extend(instance, context);
return instance;
}
// 创建实例
var axios = createInstance(defaults);
axios.Axios = Axios;
// 工厂模式 创建新的实例 用户可以自定义一些参数
axios.create = function create(instanceConfig) {
return createInstance(mergeConfig(axios.defaults, instanceConfig));
};
utils.js文件,一些工具方法,展示几个比较重要的
// utils.js 文件中几个重要方法
// forEach 用来遍历对象
// forEach 用来循环 obj 中对象,然后在 fn 中可以拿到 obj 中的 key,val,obj
function forEach(obj, fn) {
if (obj === null || typeof obj === 'undefined') { return; }
if (typeof obj !== 'object') { obj = [obj]; }
if (isArray(obj)) {
for (var i = 0, l = obj.length; i < l; i++) {
fn.call(null, obj[i], i, obj);
}
} else {
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
fn.call(null, obj[key], key, obj);
}
}
}
}
// extend 用于拷贝对象
// 将b对象中的 key val 赋给 a,然后返回a
function extend(a, b, thisArg) {
forEach(b, function assignValue(val, key) {
if (thisArg && typeof val === 'function') {
a[key] = bind(val, thisArg);
} else {
a[key] = val;
}
});
return a;
}
// helpers/bind.js bind函数
// 返回的是一个函数,该函数用来改变 this 的指向
module.exports = function bind(fn, thisArg) {
return function wrap() {
var args = new Array(arguments.length);
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i];
}
return fn.apply(thisArg, args);
};
};
defaults.js文件,用来导出默认配置
// defaults.js 文件中可以找到
function getDefaultAdapter() {
var adapter;
// 这里判断运行环境,给 adapter 赋值,浏览器就赋值xhr对象,node环境就赋值http对象
if (typeof XMLHttpRequest !== 'undefined') {
adapter = require('./adapters/xhr');
} else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {
adapter = require('./adapters/http');
}
return adapter;
}
// 将 adapter 用对象包起来导出,当然还有默认配置
var defaults = {
adapter: getDefaultAdapter(),
// 省略
}
module.exports = defaults;
core/Axios.js
// context 的构造函数
function Axios(instanceConfig) {
// 将 adapter 和一些默认配置储存起来
this.defaults = instanceConfig;
// 将包含 请求/响应拦截器 的对象 保存到 interceptors 上
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager()
};
}
// 请求方法
Axios.prototype.request = function request(config) {
// chain是一个数组,用来模拟堆栈顺序,dispatchRequest是发送请求模块
var chain = [dispatchRequest, undefined];
// 等价于 var promise = new Promise( (resolve)=> resolve(config) )
var promise = Promise.resolve(config);
// 请求拦截器将方法插入数组头部
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
chain.unshift(interceptor.fulfilled, interceptor.rejected);
});
// 相应拦截器将方法插入数组尾部
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
chain.push(interceptor.fulfilled, interceptor.rejected);
});
// 形成 promise 链
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
};
// 这是获取 Url 的函数,省略
Axios.prototype.getUri = function getUri(config) {};
// 提供一些请求方法的别名
utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
Axios.prototype[method] = function(url, config) {
return this.request(utils.merge(config || {}, {
method: method,
url: url
}));
};
});
utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
Axios.prototype[method] = function(url, data, config) {
return this.request(utils.merge(config || {}, {
method: method,
url: url,
data: data
}));
};
});
module.exports = Axios;
core/InterceptorManager.js文件 ,拦截器的构造函数和一些方法
// 拦截器的构造函数,handles 用于存储拦截器函数
function InterceptorManager() {
this.handlers = [];
}
// axios.interceptors.request.use
// axios.interceptors.response.use
// 用于注册拦截器
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
this.handlers.push({
fulfilled: fulfilled,
rejected: rejected
});
return this.handlers.length - 1;
};
// 根据id删除拦截器,类似 clearInterval
InterceptorManager.prototype.eject = function eject(id) {
if (this.handlers[id]) {
this.handlers[id] = null;
}
};
// 遍历执行所有拦截器,传递一个回调函数 (每一个拦截器函数作为参数) 调用
// 被移除的一项是null,所以不会执行,也就达到了移除的效果
InterceptorManager.prototype.forEach = function forEach(fn) {
utils.forEach(this.handlers, function forEachHandler(h) {
if (h !== null) {
fn(h);
}
});
};
module.exports = InterceptorManager;
core/dispatchRequest.js文件 用于处理适配器 adapter
module.exports = function dispatchRequest(config) {
config.headers = config.headers || {};
// 省略了部分代码,格式转换等
utils.forEach(['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
function cleanHeaderConfig(method) {
delete config.headers[method];
}
);
var adapter = config.adapter || defaults.adapter;
// 适配器执行部分
return adapter(config).then(function onAdapterResolution(response) {
return response;
}, function onAdapterRejection(reason) {
if (!isCancel(reason)) {
if (reason && reason.response) {
// 格式转换
reason.response.data = transformData(
reason.response.data,
reason.response.headers,
config.transformResponse
);
}
}
return Promise.reject(reason);
});
};
135

被折叠的 条评论
为什么被折叠?



