请求默认配置对象
我们完善defaults/index.js
文件里的默认配置对象,我们添加 timeout
参数,该参数的作用是设置请求超时时间,还提供了 validateStatus
验证响应状态码的方法,第一章 settle
函数里面的验证方法默认使用该方法。defaults.headers
对象跟请求头有关,headers.common
对象指定了请求头的通用配置,headers.common.Accept
属性指定了要接收的响应数据类型,同时我们在 headers
对象上指定了 post
, put
, patch
方法的默认 Content-Type
类型为 application/x-www-form-urlencoded
var utils = require("../utils");
var DEFAULT_CONTENT_TYPE = {
"Content-Type": "application/x-www-form-urlencoded",
};
// 获取浏览器或node环境下发http请求的adapter
// 我们只讲浏览器部分
function getDefaultAdapter() {
var adapter;
if (typeof XMLHttpRequest !== "undefined") {
// 用于发起浏览器xhr请求
adapter = require("../adapters/xhr");
}
return adapter;
}
var defaults = {
adapter: getDefaultAdapter(),
/**
* 请求的超时时间. 设为 0 表示没有超时限制
*
*/
timeout: 0,
// 验证响应状态码
validateStatus: function validateStatus(status) {
return status >= 200 && status < 300;
},
};
defaults.headers = {
common: {
Accept: "application/json, text/plain, */*",
},
};
// 没有数据的方法
utils.forEach(["delete", "get", "head"], function forEachMethodNoData(method) {
defaults.headers[method] = {};
});
// 有数据的方法,需要指定Content-Type
utils.forEach(["post", "put", "patch"], function forEachMethodWithData(method) {
// 通过merge方法,每个方法得到一个不同的对象,且该对象包含DEFAULT_CONTENT_TYPE的内容
defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE);
});
module.exports = defaults;
我们在utils.js
中来实现 merge
辅助函数
var toString = Object.prototype.toString;
// Object.create(null)创建一个缓存对象,是为了优化性能
var kindOf = (function(cache) {
return function(thing) {
var str = toString.call(thing);
// str的格式为'[object type]',str.slice(8, -1)获得type
return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase());
};
})(Object.create(null));
/**
* 判断一个值是否是纯对象
*
* @param {Object} val 要判断的值
* @return {boolean} 如果是纯对象则返回 True , 否则 false
*/
function isPlainObject(val) {
// 不是对象类型直接为false
if (kindOf(val) !== 'object') {
return false;
}
var prototype = Object.getPrototypeOf(val);
// prototype为null 或等于 Object.prototype 为纯对象
return prototype === null || prototype === Object.prototype;
}
// merge可以接收多个需要合并的对象
// 把这些对象合并后,返回一个新的对象
function merge() {
var result = {};
function assignValue(val, key) {
// isPlainObject判断一个对象时否是纯对象
if (isPlainObject(result[key]) && isPlainObject(val)) {
// 如果result[key]跟val是纯对象,则把它们合并成一个新的对象
// 并把新对象赋值给result[key]
result[key] = merge(result[key], val);
} else if (isPlainObject(val)) {
// val是一个纯对象,合并成新的对象,并重新赋值给key
// 生成新对象的目的是为了不产生副作用,当对新对象进行操作时,源对象不会受到影响
result[key] = merge({}, val);
} else if (isArray(val)) {
// 如果val是数组,则slice出一个新的数组
result[key] = val.slice();
} else {
result[key] = val;
}
}
for (var i = 0, l = arguments.length; i < l; i++) {
// 1.2小节已实现 forEach 函数
forEach(arguments[i], assignValue);
}
return result;
}