说明
axios 是基于 promise 的http库,可以用在浏览器和node.js 中来处理网络请求。
axios的特点有
- 从浏览器中创建 XMLHttpRequests
- 从 node.js 创建 http 请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求数据和响应数据
- 取消请求
- 自动转换 JSON 数据
- 客户端支持防御 [XSRF]
在一些通用配置上,可以指定默认配置
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
axios.js 入口文件
axios是源码中已经创建好的一个实例,用 axios.js 中的createInstance函数来创建。此外axios实例上挂载了许多方法
-
当有许多基于不同配置的请求时,可以利用 axios.create 创建一个新的 axios实例。
// 创建实例时设置配置的默认值 var instance = axios.create({ baseURL: 'https://api.example.com' }); // 在实例已创建后修改默认值 instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
createInstance 函数:
- new 了一个 Axios 实例 context
- 将 Axios.prototype.request 的 this 指向 context
- 将Axios.prototype 中的方法赋给 instance,并将 instance 的this指向 context
- 将 context 上的方法 赋给 instance
function createInstance(defaultConfig) {
var context = new Axios(defaultConfig);
var instance = bind(Axios.prototype.request, context);
// 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);
// };
// };
// Copy axios.prototype to instance
utils.extend(instance, Axios.prototype, context);
// 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;
// }
// Copy context to instance
utils.extend(instance, context);
return instance;
}
axios.all 其实就是 Promise.all
axios.all = function all(promises) {
return Promise.all(promises);
};
Axios.js
Axios.js 中的 axios.prototype.request 是axios 的核心函数。
- 首先将 传入的配置参数与默认的配置 合并
- 然后设置 config 的 method并将method转换成小写字母
- 创建了一个 chain并传入 两个参数:dispathRequest 和 undefined
- 将config用 promise包装
- 将请求拦截器中注册的 中间件 从chain的头部一次插入两个,将响应拦截器中注册的中间件从chain的尾部一次插入两个
- 然后一次从 chain中取出两个参数,先执行 request请求,然后到 dispathchRequest, 再执行 response 响应
- 最后返回 promise
Axios.prototype.request = function request(config) {
/*eslint no-param-reassign:0*/
// Allow for axios('example/url'[, config]) a la fetch API
if (typeof config === 'string') {
config = arguments[1] || {};
config.url = arguments[0];
} else {
config = config || {};
}
config = mergeConfig(this.defaults, config);
// Set config.method
if (config.method) {
config.method = config.method.toLowerCase();
} else if (this.defaults.method) {
config.method = this.defaults.method.toLowerCase();
} else {
config.method = 'get';
}
// Hook up interceptors middleware
var chain = [dispatchRequest, undefined];
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);
});
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
};
-
拦截器是一个数组
function Axios(instanceConfig) { this.defaults = instanceConfig; this.interceptors = { request: new InterceptorManager(), response: new InterceptorManager() }; } function InterceptorManager() { this.handlers = []; }
-
use就是将参数push进拦截器数组,一次必须传入两个参数
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
this.handlers.push({
fulfilled: fulfilled,
rejected: rejected
});
return this.handlers.length - 1;
};
dispatchRequest.js
dispatchRequest 是 Axios.prototype.request 调用的处理 axios 发起请求的参数:
-
首先判断请求是否取消
-
如果没有取消,用 transformData 将请求数据进行转换
-
利用utils.merge 将 config.headers.common || {}, config.headers[config.method] || {},config.headers 进行合并
-
删除多余的请求头
-
初始化一个适配器,如果当前环境是浏览器就是用 xhr 适配器,如果是node环境,就使用http适配器。
function getDefaultAdapter() { var adapter; if (typeof XMLHttpRequest !== 'undefined') { // For browsers use XHR adapter adapter = require('./adapters/xhr'); } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') { // For node use HTTP adapter adapter = require('./adapters/http'); } return adapter; }
-
执行适配器,返回用promise包装的 response,将 response 数据转换成如下格式
reason.response.data, reason.response.headers, config.transformResponse
module.exports = function dispatchRequest(config) {
throwIfCancellationRequested(config);
// Ensure headers exist
config.headers = config.headers || {};
// Transform request data
config.data = transformData(
config.data,
config.headers,
config.transformRequest
);
// Flatten headers
config.headers = utils.merge(
config.headers.common || {},
config.headers[config.method] || {},
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) {
throwIfCancellationRequested(config);
// Transform response data
response.data = transformData(
response.data,
response.headers,
config.transformResponse
);
return response;
}, function onAdapterRejection(reason) {
if (!isCancel(reason)) {
throwIfCancellationRequested(config);
// Transform response data
if (reason && reason.response) {
reason.response.data = transformData(
reason.response.data,
reason.response.headers,
config.transformResponse
);
}
}
return Promise.reject(reason);
});
};
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!