axios
安装axios
npm install axios --save
引用
直接script标签引用
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
也可以去GitHub上去观看原工程文件
https://github.com/axios/axios
使用
发送一个最简单的请求
这里我们发送一个带参数的get请求,params参数放在get方法的第二个参数中,如果没有参数get方法里可以只写路径。如果请求失败捕获一下异常。
axios
.get('/list',{
params: {
id: 5
}
})
.then(res => {
console.log('数据是:', res);
})
.catch((e) => {
console.log('获取数据失败');
});
当然,我们也可以发送一个POST请求,post方法的第二个参数为请求参数对象。
this.$axios.post('list',{
name: '小刘'
})
.then(function(res){
console.log(res);
})
.catch(function(err){
console.log(err);
});
一次合并发送多个请求
分别写两个请求函数,利用axios的all方法接收一个由每个请求函数组成的数组,可以一次性发送多个请求,如果全部请求成功,在axios.spread
方法接收一个回调函数,该函数的参数就是每个请求返回的结果。
function getUserAccount(){
return axios.get('/user/12345');
}
function getUserPermissions(){
return axios.get('/user/12345/permissions');
}
this.$axios.all([getUserAccount(),getUserPermissions()])
.then(axios.spread(function(res1,res2){
//当这两个请求都完成的时候会触发这个函数,两个参数分别代表返回的结果
}))
axios的API
以上通过axios直接调用发放来发起对应的请求其实是axios为了方便起见给不同的请求提供的别名方法。我们完全可以通过调用axios的API,传递一个配置对象来发起请求。
发送post请求,参数写在data属性中
axios({
url: 'list',
method: 'post',
data: {
name: '小刘'
}
}).then(res => {
console.log('请求结果:', res);
});
发送get请求,默认就是get请求,直接第一个参数写路径,第二个参数写配置对象,参数通过params属性设置。
axios('list', {
params: {
name: '小刘'
}
}).then(res => {
console.log('请求结果:', res);
});
axios为所有请求方式都提供了别名:
- axios.request(config)
- axios.get(url, [config])
- axios.delete(url, [config])
- axios.head(url, [config])
- axios.options(url, [config])
- axios.post(url, [data], [config])
- axios.put(url, [data], [config])
- axios.patch(url, [data], [config])
axios配置默认值
1、可以通过axios.defaults设置全局默认值,在所有请求中都生效。
axios.defaults.headers.common["token"] = ""
axios.defaults.headers.post["Content-type"] = "application/json"
axios.defaults.baseURL = 'https://service.xxx.com; //设置统一路径前缀
2、也可以自定义实例的默认值,以及修改实例的配置
// 创建时自定义默认配置,超时设置为全局默认值0秒
let ax = axios.create({
baseURL: 'http://123456.com',
params: { name: 'liu' }
});
// 修改配置后,超时设置为4秒
ax.defaults.timeout = 4000;
3、也可以像前面那样,在每个请求中设置相关的配置。
axios('/app', {
params: {
name: 'liu'
},
baseURL: 'http://123456.com'
})
{
method:'请求方法',
baseURL:'如果路径不是绝对路径,就会在路径前自动添加此路径',
transformRequest: [(data, header)=>{}], //在发送请求之前修改数据,适用于post、put、patch
transformResponse: [(data)=>{
return JSON.parse(data).data;
}], //在收到的数据传到then之前修改数据,注意这里data是个字符串类型。
header: {'X-Requested-With': 'XMLHttpRequest'}, //请求头
params: {}, //请求参数
paramsSerializer: (params)=>{
return qs.stringify(params); //name=xiaohong&id=1
} //可选函数,可以把参数拼接成字符串
data: {}, // post类方法的请求体参数
timeout: 0, //请求延时事件,如果超时请求终止
withCredentials: false, //是否时跨站点请求
onUploadProgress: (progressEvent)=>{
//可以通过progressEvent拿到上传的进度
},
onDownloadProgress: ()=>{},//和onUploadProgress一样,获取下载的进度
responseType: json, // 返回的数据格式
maxContentLength: 2000, //相应内容的最大尺寸
validateStatus: (validateStatus)=>{
return validateStatus >= 200; //限制相应状态码,如果不满足就拒绝
},
cancelToken: new cancelToken(function(cancel){}) // 指定一个取消请求标识,下面会用到
}
拦截器
可以分别设置请求拦截和响应拦截,在发出请求和响应到达then之前进行判断处理。
//添加一个请求拦截器
axios.interceptors.request.use(function(config){
//在请求发出之前进行一些操作
return config;
},function(err){
//Do something with request error
return Promise.reject(error);
});
//添加一个响应拦截器
axios.interceptors.response.use(function(res){
//在这里对返回的数据进行处理
return res;
},function(err){
//Do something with response error
return Promise.reject(error);
})
以上以相应拦截器为例,请求拦截器同样,只是把response换成request。第一个参数是成功回调,第二个是错误回调。
也可以移除拦截器,就像移除js定时器一样的操作:
var myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);
跨域配置
如果我们要跨域请求数据,在配置文件里设置代理,vue-cli3项目,需要在根目录自己创建一个vue.config.js,在里面写配置。
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'https://www.xxx.com', //目标路径,别忘了加http和端口号
changeOrigin: true, //是否跨域
ws: true,
pathRewrite: {
'^/api': '' //重写路径
}
}
}
}
};
调用接口:
axios.post('/api/test', {name: 'xiao'});
如果没有重写路径,访问的就是https://www.xxx.com/api/test
,如果像上面代码那样重写路径访问的就是https://www.xxx.com/test
。
原理:
因为客户端请求服务端的数据是存在跨域问题的,而服务器和服务器之间可以相互请求数据,是没有跨域的概念(如果服务器没有设置禁止跨域的权限问题)
使用Promise封装自己的Ajax库
// const axios = require("../axios/axios");
;(function anonymous(window){
// 设置默认配置项
let _default = {
method: "GET",
url : "",
baseURL : "",
headers : {},
dataType : "JSON",
data:null, //=》post系列请求基于问号传参传递给服务器的内容
params : null, //=> get系列请求基于问号传参传递给服务器的内容,
cache : true
}
// 基于promise设计模式管理AJAX请求
let ajaxPromise = function ajaxPromise(options){
// options中融合了:默认配置信息,基于用户defaults修改的信息,用户执行get/post配置请求时,越靠后优先级越高
let {
url,baseURL,method,data,dataType,headers,cache,params
} = options;
//把传递的参数进一步处理
if(/^(GET|DELETE|HEAD|OPTIONS)$/i.test(method)){
// GET系列
if(params){
url += `${ajaxPromise.check(url)}${ajaxPromise.formatData(params)}`
}
if(cache === false){
url += `${ajaxPromise.check(url)}_=${+(new Date())}`
}
data = null //=>GET系列请求主体就是什么都不放
}else{
// POST系列
if(data){
data = ajaxPromise.formatData(data)
}
}
// 基于promise发送Ajax
return new Promise((resolve,reject)=>{
let xhr = new XMLHttpRequest
xhr.open(method,`${baseURL}${url}`)
//=>如果出现headers 就要设置请求头
if(headers !==null && typeof headers === "object"){
for (let attr in headers){
if (headers.hasOwnProperty(attr)){
let val = headers[attr]
if(/[\u4e00-\u9fa5]/.test(val)){
//val中包含中文 我们进行编码encodeURLComponent/decodeURLComponent
val = encodeURIComponent(val)
}
xhr.setRequestHeader(attr,headers[attr])
}
}
}
xhr.onreadystatechange = () =>{
if(xhr.readyState ===4){
if(/^(2|3)\d{2}$/.test(xhr.status)){
let result = xhr.responseText
dataType = dataType.toUpperCase()
dataType === 'JSON' ? result = JSON.parse(result) : (dataType === 'XML' ? result = xhr.responseXML :null)
resolve(result,xhr)
return;
}
reject(xhr.statusText,xhr);
}
}
xhr.send(data)
})
};
// 把对象转化为URLENCODE格式的字符串
ajaxPromise.formatData = function formatData(obj){
let str = "";
for (let attr in obj){
if(obj.hasOwnProperty(attr)){
str += `${attr}=${obj[attr]}&`
}
}
return str.substring(0,str.length - 1)
}
ajaxPromise.check = function check(url){
return url.indexOf('?') > -1 ? '&' : '?';
};
// =>GET
['get','delete','head','options'].forEach(item=>{
ajaxPromise[item] = function anonymous(url,options = {}){
options = {
..._default, //默认值或者基于defaults修改的值
...options, //用户调取方法传递的配置项
url : url, //请求的url的地址(第一个参数:默认配置项和传递的配置项中对不会出现url,只能这样获取)
method : item.toUpperCase() ///以后执行肯定是ajaxPromise.head执行,不会设置methods这个配置项,我们自己需要配置才可以
}
return ajaxPromise(options)
}
});
// post
['post','put','patch'].forEach(item=>{
ajaxPromise[item] = function anonymous(url,data={},options = {}){
options = {
..._default,
...options,
url : url,
method : item.toUpperCase(),
data : data
}
return ajaxPromise(options)
}
});
ajaxPromise.get = function (url,options){
};
ajaxPromise.post = function (url,data,options){
};
//把默认配置暴漏出去
ajaxPromise.defaults = _default
window.ajaxPromise = ajaxPromise;
})(window)