今天来谈一谈有关vue项目中使用Ajax插件库axios,以及对它做的一些封装。
安装就不再提了,在这axios;
1.简单使用
axios.post('/user' , {
params: {
firstName: 'Fred',
lastName: 'Flintstone'
}
}).then(function (response) {
console.log(response);
}).catch(function (error) {
console.log(error);
});
无需多言,一目了然。
对于接口地址我们需要处理一下跨域问题:
使用http-proxy-middleware 代理解决:
例如请求的url:“http://f.apiplus.cn/bj11x5.json”
a、打开config/index.js,在proxyTable中添写如下代码:
proxyTable: {
'/api': { //使用"/api"来代替"http://f.apiplus.c"
target: 'http://f.apiplus.cn', //源地址
changeOrigin: true, //改变源
pathRewrite: {
'^/api': 'http://f.apiplus.cn' //路径重写
}
}
}
b.使用时
getData () {
axios.get('/api/bj11x5.json', function (res) {
console.log(res)
})
c.通过这中方法去解决跨域,打包部署时还按这种方法会出问题。解决方法如下:
let serverUrl = '/api/' //本地调试时
// let serverUrl = 'http://f.apiplus.cn/' //打包部署上线时
export default {
dataUrl: serverUrl + 'bj11x5.json'
}
但是这种解决方法处理时,当线上的域名与接口不一致时会出现同一个请求发送两次的问题。网上说的解决方式是在请求头部加上Access-Control-Max-Age(单位s),这个是预检请求的时间,只要设置的时间足够长就能解决该问题,(Chrome时间上限为600s),然而亲测无效。大家可以试试。
2.axios拦截器
axios拦截器有两种,请求拦截和响应拦截,其目的是为了在接口请求和响应时统一地处理一些事情,比如网络错误,后端抛出的错误。
import axios from 'axios'
// 添加一个请求拦截器
axios.interceptors.request.use(config => {
// Do something before request is sent
return config
}, error => {
// Do something with request error
return Promise.reject(error)
});
// 添加一个响应拦截器
axios.interceptors.response.use(response => {
// Do something with response data
return response
}, error => {
// Do something with response error
return Promise.resolve(error.response)
});
在这里我们并没有在拦截器里面处理我们需要处理的事情,当然你可以这么做。我们用promise链式处理接口异常。
3.封装
处理方式如下:
request(obj) {
return new Promise((resolve, reject) => {
axios({
method: obj.method,
baseURL: obj.baseUrl,
url: obj.path,
data: obj.method === 'post' ? obj.params : {},
params: obj.method === 'get' ? obj.params : {},
timeout: 20000,
withCredentials: true,
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
}).then((res) => {
return _checkStatus(res)
}).then((res) => {
if (res.retCode !== 0) {
if (obj.showErr) {
// 如果retCode异常(这里包括后端抛出的错误),可以弹出一个错误提示,告诉用户
Message({showClose: true, message: res.retMsg, type: 'warning'});
} else {
return reject(res)
}
} else {
return resolve(res)
}
}).catch((err) => {
return reject({retMsg: '未知错误', retCode: 500})
})
})
}
这里处理接口异常情况主要有两种,第一种是code码异常也就是code为非200状态,第二种是接口返回数据异常(retCode异常)。第一种情况我们用_checkStatus()处理的,具体如下:
function _checkStatus(response) {
// loading
// 如果http状态码正常,则直接返回数据
if (response && (response.status === 200 || response.status === 304 || response.status === 400)) {
return response;
}
// 异常状态下,把错误信息返回去
return {
status: -404,
msg: '网络异常'
}
}
第二种情况 我们这么处理的:
if (res.retCode !== 0) {
if (obj.showErr) {
_dealCode(res);
} else {
return reject(res)
}
} else {
return resolve(res)
}
解释下,这里的showErr是控制是否统一处理错误,有时候我们需要单独去处理一些特殊情况的错误反馈。这里的res.retcode!==0表示http状态码正确(接口连接正常),但返回的数据有问题,不同的retCode代表不同的意思,这个可以跟后端约定好,后端会把数据异常原因放在retMsg里面,比如和后端约定好retCode===999时,表示传参出错,retMsg = ‘传参错误’。
正常情况下我们直接统一弹出一个错误提示给用户就好了,但有时候需要特殊处理此时chua传参数时showErr=false即可.
调用时这么做即可:
this.$http.request({'https://baishsd.com/', path: 'newCost/Report/ChartAcpe', params, method:'post',showErr:true}).then(res => {})
使用时加上showErr,无需catch捕获异常,已统一处理。
不过这么写参数还是麻烦了一点,可以自己封装下参数,全部写在app.js中统一放置接口,统一管理