参加若川源码共读活动
1.什么是Axios
Axios 是一个基于 Promise 的 HTTP 客户端,拥有以下特性:
- 支持 Promise API;
- 能够拦截请求和响应;
- 能够转换请求和响应数据;
- 客户端支持防御 CSRF 攻击;
- 同时支持浏览器和 Node.js 环境;
- 能够取消请求及自动转换 JSON 数据。
2.工具函数
下面所说的工具函数,都是位于utils.js中的
var toString = Object.prototype.toString;
/**
* 确定值是否为数组
* @param {Object} val 要测试的值
* @returns {boolean} 如果值是数组,则为 true,否则为 false
*/
function isArray(val) {
return Array.isArray(val);
}
/**\
* 确定值是否未定义\
*\
* @param {Object} val 要测试的值\
* @returns {boolean} 如果值未定义,则为 true,否则为 false\
*/
function isUndefined(val) {
return typeof val === 'undefined';
}
/**\
* 确定值是否为缓冲区\
*\
* @param {Object} val 要测试的值\
* @returns {布尔} 如果值是缓冲区,则为 true,否则为 false\
*/
function isBuffer(val) {
return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor)
&& typeof val.constructor.isBuffer === 'function' && val.constructor.isBuffer(val);
}
/**\
* 确定某个值是否为阵列缓冲区\
*\
* @param {Object} val 要测试的值\
* @returns {boolean} True,如果值是 ArrayBuffer,则为 false\
*/
function isArrayBuffer(val) {
return toString.call(val) === '[object ArrayBuffer]';
}
/**\
* 确定值是否为阵列缓冲区上的视图\
*\
* @param {Object} val 要测试的值\
* @returns {boolean} True,如果值是 ArrayBuffer 上的视图,否则为 false\
*/
function isArrayBufferView(val) {
var result;
if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {
result = ArrayBuffer.isView(val);
} else {
result = (val) && (val.buffer) && (isArrayBuffer(val.buffer));
}
return result;
}
/**\
* 确定值是否为字符串\
*\
* @param {Object} val 要测试的值\
* @returns {boolean} 如果值是字符串,则为 true,否则为 false\
*/
function isString(val) {
return typeof val === 'string';
}
/**\
* 确定值是否为数字\
*\
* @param {Object} val 要测试的值\
* @returns {布尔} 如果值为数字,则为 true,否则为 false\
*/
function isNumber(val) {
return typeof val === 'number';
}
/**\
* 确定值是否为对象\
*\
* @param {Object} val 要测试的值\
* @returns {boolean} 如果值是对象,则为 true,否则为 false\
*/
function isObject(val) {
return val !== null && typeof val === 'object';
}
/**\
* 确定值是否为普通对象\
*\
* @param {Object} val 要测试的值\
* @return {boolean} True,如果值是普通对象,否则为 false\
*/
function isPlainObject(val) {
if (toString.call(val) !== '[object Object]') {
return false;
}
var prototype = Object.getPrototypeOf(val);
return prototype === null || prototype === Object.prototype;
}
/**\
* 确定值是否为日期\
*\
* @param {Object} val 要测试的值\
* @returns {boolean} 如果值是 Date,则为 true,否则为 false\
*/
function isDate(val) {
return toString.call(val) === '[object Date]';
}
/**\
* 确定值是否为文件\
*\
* @param {Object} val 要测试的值\
* @returns {boolean} 如果值是文件,则为 true,否则为 false\
*/
function isFile(val) {
return toString.call(val) === '[object File]';
}
/**\
* 确定值是否为 Blob\
*\
* @param {Object} val 要测试的值\
* @returns {boolean} True,如果值是 Blob,则为 false\
*/
function isBlob(val) {
return toString.call(val) === '[object Blob]';
}
/**\
* 确定值是否为函数\
*\
* @param {Object} val 要测试的值\
* @returns {boolean} 如果值是函数,则为 true,否则为 false\
*/
function isFunction(val) {
return toString.call(val) === '[object Function]';
}
/**\
* 确定某个值是否为流\
*\
* @param {Object} val 要测试的值\
* @returns {boolean} 如果值是流,则为 true,否则为 false\
*/
function isStream(val) {
return isObject(val) && isFunction(val.pipe);
}
/**\
* 确定值是否为表单数据\
*\
* @param {对象} 事物 要测试的值\
* @returns {boolean} True,如果值是 FormData,则为 false\
*/
function isFormData(thing) {
var pattern = '[object FormData]';
return thing && (
(typeof FormData === 'function' && thing instanceof FormData) ||
toString.call(thing) === pattern ||
(isFunction(thing.toString) && thing.toString() === pattern)
);
}
/**\
* 确定某个值是否为 URLSearchParams 对象\
*\
* @param {Object} val 要测试的值\
* @returns {boolean} True,如果值是 URLSearchParams 对象,否则为 false\
*/
function isURLSearchParams(val) {
return toString.call(val) === '[object URLSearchParams]';
}
/**\
* 修剪字符串开头和结尾多余的空格\
*\
* @param {String} str 要修剪的字符串\
* @returns {String} 释放多余空格的字符串\
*/
function trim(str) {
return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '');
}
/**\
* 确定我们是否在标准浏览器环境中运行\
*\
* 这允许 axios 在 Web worker 中运行,并进行本机反应。\
* 这两种环境都支持 XMLHttpRequest,但不是完全标准的全局环境。\
*\
* 网络工作者:\
* 窗口类型 -未定义>\
* 文件类型 -未定义>
* 反应原生:\
* navigator.product -> 'ReactNative'\
* 本地脚本\
* navigator.product -> 'NativeScript' or 'NS'\
*/
function isStandardBrowserEnv() {
if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative' ||
navigator.product === 'NativeScript' ||
navigator.product === 'NS')) {
return false;
}
return (
typeof window !== 'undefined' &&
typeof document !== 'undefined'
);
}
/**\
* 循环访问为每个项调用函数的数组或对象。\
*\
* 如果'obj'是数组回调将称为传递\
* 每个项的值、索引和完整数组。\
*\
* 如果'obj'是一个对象回调将被称为传递\
* 每个属性的值、键和完整对象。
* @param {对象|Array} obj 要迭代的对象\
* @param {Function} fn 要为每个项调用的回调\
*/
function forEach(obj, fn) {
// Don't bother if no value provided
if (obj === null || typeof obj === 'undefined') {
return;
}
// Force an array if not already something iterable
if (typeof obj !== 'object') {
/*eslint no-param-reassign:0*/
obj = [obj];
}
if (isArray(obj)) {
// Iterate over array values
for (var i = 0, l = obj.length; i < l; i++) {
fn.call(null, obj[i], i, obj);
}
} else {
// Iterate over object keys
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
fn.call(null, obj[key], key, obj);
}
}
}
}
/**\
* 接受 varargs 期望每个参数都是一个对象,然后\
* 不可变地合并每个对象的属性并返回结果。\
*\
* 当多个对象包含相同的键时,后面的对象\
* 参数列表将优先。\
*\
* 例:\
*\
* ""js\
* var result = merge({foo: 123}, {foo: 456});\
* console.log(result.foo);输出 456\
* ```\
*\
* @param {Object} obj1 要合并的对象\
* @returns {对象} 所有合并属性的结果\
*/
function merge(/* obj1, obj2, obj3, ... */) {
var result = {};
function assignValue(val, key) {
if (isPlainObject(result[key]) && isPlainObject(val)) {
result[key] = merge(result[key], val);
} else if (isPlainObject(val)) {
result[key] = merge({}, val);
} else if (isArray(val)) {
result[key] = val.slice();
} else {
result[key] = val;
}
}
for (var i = 0, l = arguments.length; i < l; i++) {
forEach(arguments[i], assignValue);
}
return result;
}
/**\
* 通过向对象 a 添加对象 b 的属性来扩展对象 a。\
*\
* @param {Object} a 要扩展的对象\
* @param {对象} b 要从中复制属性的对象\
* @param {Object} thisArg 要将函数绑定到的对象\
* @return {对象} 对象 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;
}