网络模块封装axios
模块的选择
Vue中发送网络请求有非常多的方式, 那么, 在开发中, 如何选择呢?
- 传统的Ajax是基于XMLHttpRequest(XHR)
- 使用jQuery-Ajax
- 官方在Vue1.x的时候, 推出了Vue-resource
- axios
比较差异: 传统的Ajax配置和调用方式等非常混乱.编码起来看起来就非常蛋疼.所以真实开发中很少直接使用, 而jQuery-Ajax,在Vue的整个开发中都是不需要使用jQuery了.为了方便我们进行一个网络请求, 特意引用一个jQuery,
你觉得合理吗?完全没有必要为了用网络请求就引用这个重量级的框架.Vue作者就在GitHub的Issues中说明了去掉vue-resource, 并且以后也不会再更新.那么意味着以后vue-reource不再支持新的版本时, 也不会再继续更新和维护.
对以后的项目开发和维护都存在很大的隐患.
综上,我们使用axios作为发送网络请求的模块
认识axios
基于promise用于浏览器和node.js的http客户端
功能特点:
- 支持浏览器和node.js
- 支持promise
- 能拦截请求和响应
- 能转换请求和响应数据
- 自动转换JSON数据
- 浏览器端支持防止CSRF(跨站请求伪造)
发送基本请求
HttpBin 介绍
httpbin
是一个HTTP Request & Response Service
,你可以向他发送请求,然后他会按照指定的规则将你的请求返回。这个类似于echo服务器
,但是功能又比它要更强大一些。 httpbin
支持HTTP/HTTPS,支持所有的HTTP动词,能模拟302跳转乃至302跳转的次数,还可以返回一个HTML文件或一个XML文件或一个图片文件(还支持指定返回图片的格式)。实在是请求调试中居家必备的良器!
httpbin怎么用
httpbin
的使用方法非常简单,你只需要把请求的地址修改为httpbin.org
即可。 比如:
curl http://httpbin.org/user-agent
查看自己的GET请求
curl http://httpbin.org/get
Get request
#Get request
//没有请求参数
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Post request
#Post request
//有请求参数
axios.post('/save', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
发送并发请求
有时候, 我们可能需求同时发送两个请求.使用axios.all, 可以放入多个请求的数组.axios.all([])
返回的结果是一个数组,使用 axios.spread
可将数组 [res1,res2]
展开为 res1, res2
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread((acct, perms)=>{
console.info(acct);
console.info(perms);
}));
可用的api别名
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]])
#注:当使用以上别名方法时,url,method和data等属性不用在config重复声明。
#全局配置
在上面的示例中, 我们的BaseURL
是固定的.事实上, 在开发中可能很多参数都是固定的.这个时候我们可以进行一些抽取, 也可以利用axiox
的全局配置
//提取全局配置
axios.defaults.baseURL = ‘http://123.207.32.32:8000’
axios.defaults.headers.post[‘Content-Type’] = ‘application/x-www-form-urlencoded’;
//发送并发请求
axios.all([
axios.get('/user/12345'),
axios.get('/user/12345/permissions')])
.then(axios.spread((acct, perms)=>{
console.info(acct);
console.info(perms);
}));
常见的配置选项
请求地址 | url: ‘/user’ |
---|---|
请求类型 | method: ‘get’, |
请根路径 | baseURL: ‘http://www.mt.com/api’, |
请求前的数据处理 | transformRequest:[function(data){}], |
请求后的数据处理 | transformResponse: [function(data){}], |
自定义的请求头 | headers:{‘x-Requested-With’:‘XMLHttpRequest’}, |
URL查询对象 | params:{ id: 12 }, |
查询对象序列化函数 | paramsSerializer: function(params){ } |
request body | data: { key: ‘aa’}, |
超时设置s | timeout: 1000, |
跨域是否带Token | withCredentials: false, |
自定义请求处理 | adapter: function(resolve, reject, config){}, |
身份验证信息 | auth: { uname: ‘’, pwd: ‘12’}, |
响应的数据格式 json / blob /document /arraybuffer / text / stream | responseType: ‘json’, |
axios实例
为什么要创建
axios
的实例呢?
当我们从axios
模块中导入对象时, 使用的实例是默认的实例.当给该实例设置一些默认配置时, 这些配置就被固定下来了.但是后续开发中, 某些配置可能会不太一样.比如某些请求需要使用特定的baseURL
或者timeout
或者content-Type
等.这个时候, 我们就可以创建新的实例, 并且传入属于该实例的配置信息.
拦截器
axios提供了拦截器,用于我们在发送每次请求或者得到相应后,进行对应的处理。
拦截器语法
// 添加一个请求拦截器
axios.interceptors.request.use(function (response) {
console.info("来到了request拦截的success中")
return response;
}, function (error) {
console.info("来到了request拦截的error中")
return error;
});
// 添加一个响应的拦截器
axios.interceptors.response.use(function (response) {
console.info("来到了response拦截的success中")
return response.data;
}, function (error) {
console.info("来到了response拦截的error中")
return error;
});
拦截器中都做什么呢?
请求拦截可以做到的事情:
- 当发送网络请求时,在页面中添加一个loading组件,作为动画
- 某些请求要求用户必须登入,判断用户是否有token,如果没有token跳到login页面
- 对请求参数进行序列化
添加响应拦截器,统一处理服务器响应和异常
/**
* 添加响应拦截器,统一处理服务器响应和异常
*/
axios.interceptors.response.use(
response => {
return response
},
error => {
/**
* 状态码401代表无权限访问,权限失效,需要重新获取authToken
* 状态码500代表REST服务器异常
*/
const status = error.response.status
const message = error.response.data.meta.message
if (status === 401) {
/**
* 登录授权token超时,提示
*/
if (message.indexOf('ERROR_CODE_001') > -1) {
this.$message.error(errorCode.ERROR_CODE_001)
}
window.location.href = `${window.location.origin}/login`
return Promise.reject(error)
}
/**
* 1.处理系统服务异常
* 2.处理SoaException异常
*/
if (status === 500) {
if (message.indexOf('ERROR_CODE_003') > -1) {
this.$message.error(errorCode.ERROR_CODE_003)
return
}
this.$message.error(message)
}
return Promise.reject(error)
}
)
封装axios api http.js,便捷方法调用
/**
* http.js
* 封装axios,
* 调用方法:
* http.get('/api/enquiry/web/query',{id:1}).then((res)=>{你的操作})
* http.post('/api/enquiry/web/update',{id:1}).then((res)=>{你的操作})
* http.postFormData('/api/enquiry/web/update',{id:1,file:file}).then((res)=>{你的操作})
*/
import axios from 'axios'
export default {
/**
* get方法,对应get请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
get (url, params) {
return new Promise((resolve, reject) => {
axios.get(url, {
params: params
}).then(res => {
resolve(res.data)
}).catch(err => {
reject(err)
})
})
},
/**
* post方法,对应post请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
post (url, params) {
return new Promise((resolve, reject) => {
axios.post(url, params)
.then(res => {
resolve(res.data)
})
.catch(err => {
reject(err)
})
})
},
/**
* postFormData方法,对应post请求,用来提交文件+数据
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
postFormData (url, params) {
return new Promise((resolve, reject) => {
axios({
headers: {
'Content-Type': 'multipart/form-data'// ;boundary=----WebKitFormBoundaryQ6d2Qh69dv9wad2u
},
transformRequest: [function (data) { // 在请求之前对data传参进行格式转换
const formData = new FormData()
Object.keys(data).forEach(key => {
formData.append(key, data[key])
})
return formData
}],
url,
method: 'post',
data: params
}).then(res => {
resolve(res.data)
}).catch(err => {
reject(err)
})
})
}
}