axios现在很火,本人觉得用的人比Ajax多一些,现在都用框架开发,而且使用Ajax要安装jQuery,好像有个人单独抽离出来,从来没用过,所以导致axios现在用的很多,今天随便学一些。
axios基于promise的HTTP库,能设置请求和相应拦截,可以处理请求和响应数据,内部好像还支持防御CSRF跨站请求伪造攻击,浏览器和nodejs都可以使用,使用方法的API就不多说介绍了,可以去看看文档:
http://www.axios-js.com/zh-cn/docs/
先说说浏览器和nodejs环境的判断,主要在下面的方法里面,也叫适配器:
function getDefaultAdapter() {
var adapter;
if (typeof XMLHttpRequest !== 'undefined') {
// For browsers use XHR adapter
adapter = __webpack_require__(12);
} else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {
// For node use HTTP adapter
adapter = __webpack_require__(12);
}
return adapter;
}
其实蛮简单的,判断对象是否能使用,然后适配器adapter就导入对应的对象。一般我们用的是默认的,axios允许自定义,提供了adapter参数:
// `adapter` 允许自定义处理请求,以使测试更轻松
// 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
adapter: function (config) {
/* ... */
},
如果用了自定义的适配器,就是走自己的方法,返回的是自定义的内容,网上那些自定义适配器的,我都试了一下,没什么意义,有些直接都是走不通,一般我们也不会自定义适配器,只是了解一下,说不定哪天真的需要就要好好研究:
function myAdapter(config) {
return new Promise((resolve, reject) => {
resolve({
a: 20,
data: {}
})
});
}
axios.defaults.adapter = myAdapter;
axios.get('').then(res => {
console.log(res)
})
axios的请求和响应拦截是使用的核心,其实就是发起请求之前和拿到响应之后的处理,如果我们自己写一个XMLHttpRequest,我们也很容易处理,只不过我们用起来有点类似发布订阅,先看看两个方法,相当于注册了:
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager()
};
function InterceptorManager() {
this.handlers = [];
}
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
this.handlers.push({
fulfilled: fulfilled,
rejected: rejected
});
return this.handlers.length - 1;
};
调用:
var chain = [dispatchRequest, undefined];
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());
}
循环数组调用之前注册的请求拦截和响应拦截。
至于其他的api,其实都是XMLHttpRequest内部支持的,比如:
设置超时:XMLHttpRequest.timeout
设置header:XMLHttpRequest.setRequestHeader()
允许携带cookie:XMLHttpRequest.withCredentials
上传进度:XMLHttpRequest.upload
这边提一嘴,axios自带的提供了CSRF攻击的防御,从来没用过,也不知道怎么测试有没有效果:
// `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称
xsrfCookieName: 'XSRF-TOKEN', // default
// `xsrfHeaderName` is the name of the http header that carries the xsrf token value
xsrfHeaderName: 'X-XSRF-TOKEN', // default
一直没用过取消请求,这其实也是XMLHttpRequest内置方法:
XMLHttpRequest.abort()
我写了一个接口,延迟三秒返回:
const http=require('http');
http.createServer(function(requset,response){
setTimeout(() => {
response.end('{a: 10}');
}, 3000)
}).listen(3001);
然后延时两秒终止:
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('http://192.168.2.132:3001/', {
cancelToken: source.token
}).then(res => {
console.log(res.data)
})
setTimeout(() => {
source.cancel()
}, 2000)
可以源码内部搜索request.abort();
还有一个点,公司现在项目接口是restful规范,所以之前调用接口,除了get方法,另外的参数不能拼接到地址上面,当时没注意,有些用data传参,有些用params传参,params传参的都会拼接到地址上面。
其实有时候想想看一看这些内部的代码好像没什么意义,因为记不下来,实现的设计模式和思想也是看过就忘了,就当作自己做点无意义的学习吧。