一:了解axios
基本概念:
axios是基于promise用于浏览器和Node.js的HTTP客户端,或者说axios是基于promise的异步Ajax请求库
特点:(gitHub有详细的介绍)
二:axios原理
实质上说,axios是Axios.prototype.request函数bind()返回的函数,从功能上说,axios可以是Axios原型的实例
axios有Axios原型上的所有方法和属性 我们从源码角度分析下axios的工作流程(粗略分析)
//创建axios新实例
function createInstance(defaultConfig) {
var context = new Axios(defaultConfig);
var instance = bind(Axios.prototype.request, context);
// Copy axios.prototype to instance
//将Axios原型对象的方法绑定到新实例(axios)上
utils.extend(instance, Axios.prototype, context);
// Copy context to instance
//将Axios原型上的属性添加到新实例上(axios) 拦截器(interceptors)和默认配置(default)
utils.extend(instance, context);
return instance;
}
// 使用默认配置创建axios
var axios = createInstance(defaults);
从上述源代码可以看出axios就是Axios.prototype.request函数bind()返回的函数,既然如此,我们Axios中有什么
为请求方法提供别名
utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
/*eslint func-names:0*/
Axios.prototype[method] = function(url, config) {
return this.request(utils.merge(config || {}, {
method: method,
url: url
}));
};
});
utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
/*eslint func-names:0*/
Axios.prototype[method] = function(url, data, config) {
return this.request(utils.merge(config || {}, {
method: method,
url: url,
data: data
}));
};
});
request()函数
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) {
//请求拦截器头部插入,fulfilled成功回调,rejected失败回调
chain.unshift(interceptor.fulfilled, interceptor.rejected);
});
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
//响应拦截器尾部追加,fulfilled成功回调,rejected失败回调
chain.push(interceptor.fulfilled, interceptor.rejected);
});
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
};
在request函数中,使用promise将请求拦截器的回调 / dispatchRequest / 响应拦截器 串联起来。这样便符合逻辑了,执行顺序 请求拦截器—>发送请求—>响应拦截器。这也可以解释一个问题,为什么我们在添加请求拦截器时执行顺序是倒的。因为promise在串联请求拦截器时采用的是头部追加。既然其他地方都没有关于请求,我们就再去看dispatchRequest
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);
// 转换响应数据
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);
});
};
主要是在发起请求前处理请求数据 / Adapter发送请求 / 发起请求后处理响应数据
既然如此,我们再去看看Adapter
有这样几个语句
......
var request = new XMLHttpRequest();
......
request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true);
......
request.send(requestData);
到这里就清除了,axios其实就是对ajax做了封装处理
总结
axios的工作原理及流程如下:
三 :其他内容
**
axios与Instance:
Instance是axios.create()创建出的实例对象
相同点:
Instance与axios都能发送任意方式的请求,(get/post…)
都有发送特定请求的方法
都有默认配置和拦截器配置
不同点:
axios.create = function create(instanceConfig) {
//mergeConfig 合并
return createInstance(mergeConfig(axios.defaults, instanceConfig));
};
Instance与axios的配置不同(config参数为空例外)
Instance没有axios新增的属性和方法 ,比如create(),CancelToken(),all(),Axios…
Instance没有取消请求和批发请求
为什么要用Instance:
项目中多个接口,接口的配置不全部相同,创建两个新的instance,每个都有自己的配置,这样就很好解决
大佬勿喷,小白一只