在fetch和axios两者之间,对比fetch的某些功能的缺失,如中断请求,进度条实现,最终选择了axios,而且在axios中,还扩张了不少功能,如拦截器,允许转换请求数据和响应数据等
- 安装
npm install axios
调用(考虑到基本每个页面都会使用到该方法,且该功能同时还需要搭配加载层,统一处理错误等,故我将axios二次封装在action.js中,在action中支持异步操作及触发多个commit)
生成全局axios对象并添加全局拦截器
/*
* 请求数据接口拦截器处理
*/
let _axios = axios.create();
//添加请求拦截器
_axios.interceptors.request.use(function(configuration){
//在发送请求之前做某事
// 值得注意的是,当type为get时,axios的传参key为params,其它均为data
let data,key;
if(configuration.method.toLowerCase() !== 'get') {
data = configuration.data;
key = 'data';
} else {
data = configuration.params;
key = 'params';
}
if(typeof(data) === 'string' ) {
data += '&reqChannelType=' + config.platform + '&reqFlowNo=' + dateUtils.getNowRandomTimes();
} else {
data['reqChannelType'] = config.platform; // 使用平台标识
data['reqFlowNo'] = dateUtils.getNowRandomTimes(); // 请求流水号
}
configuration[key] = data;
return configuration;
}, function(error){
//请求错误时做些事
return Promise.reject(error);
});
//添加响应拦截器
_axios.interceptors.response.use(function(response){
//对响应数据做些事
return response;
}, function(error){
//请求错误时做些事
return Promise.reject(error);
});
- 封装请求方法
// 本人项目接口返回数据做了特殊处理,故错误处理相对简单点
$ajax({commit, state}, {
url,
type, // 默认POST
data,
responseType,
withCredentials, // 跨域时,请求是否带上cookie,默认true
headers,
timeout,
isShowWait, // 是否显示加载层,默认true
isLastRequest, // 是否为最后一个请求,默认true
errorCatch, // 是否捕捉错误信息,默认false(一旦捕捉错误,调用时会返回错误信息)
onUploadProgress,
onDownloadProgress
}) {
const requestDataType = type && type.toLowerCase() === 'get' ? 'params' : 'data';
let setHeaders = {
'X-Requested-with' : 'XMLHttpRequest',
'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8'
};
if(typeof(headers) == "object" && Object.prototype.toString.call(headers).toLowerCase() == "[object object]" && !headers.length) {
for(let index in headers) {
if(index.toLowerCase() !== 'x-requested-with' && index.toLowerCase() !== 'content-type') {
setHeaders[index] = headers.index;
}
}
}
// 修改状态值,是否显示加载层
const iShowWait = isShowWait === false ? false : true;
const iLastRequest = isLastRequest === false ? false : true;
return new Promise((resolve, reject) => {
_axios({
'url' : url || config.serverPath,
'method' : type || 'POST',
'responseType' : responseType || 'json',
[requestDataType] : data || {},
'withCredentials' : withCredentials === false ? false : true,
'headers' : setHeaders,
'timeout' : timeout || config.ajaxTimeout * 1000,
'onUploadProgress' : onUploadProgress || function() {},
'onDownloadProgress' : onDownloadProgress || function() {},
'transformRequest' : [function (data) {
//`transformRequest`允许请求的数据在传到服务器之前进行转化。这个只适用于`PUT`,`GET`,`PATCH`方法。
// 该方法在请求拦截器之后执行
// 修改加载层状态值(这是本人开发的一个类似转菊花的等待层组件)
commit(muType.CHANGE_ILOADING, {iShowWait, iLastRequest});
let str = ''
for (let it in data) {
if(str) {
str += '&';
}
str += encodeURIComponent(it) + '=' + encodeURIComponent(data[it])
}
return str
}],
'transformResponse' : [function(data){
//`transformResponse`允许返回的数据传入then/catch之前进行处理,报错不会经过该方法
// 该方法在响应拦截器之前执行
return data;
}]
}).then(res => {
// 由于该项目对接口返回出参进行了封装,需要这里的成功不一定是请求成功
let data = res.data,
error_no = data.error_no,
error_info = data.error_info;
if(error_no == 0) {
// 请求成功
// 修改加载层状态值
let closeLoading = true;
commit(muType.CHANGE_ILOADING, {closeLoading, iLastRequest});
var results = getReqResultList(data);
resolve(results);
} else {
// 请求失败
// 修改加载层状态值
let clearLoading = true;
commit(muType.CHANGE_ILOADING, {clearLoading});
MessageBox.alert(error_info);
if(errorCatch) {
reject(res);
}
}
}).catch(err => {
// 修改加载层状态值
let clearLoading = true;
commit(muType.CHANGE_ILOADING, {clearLoading});
if((err + '').search('timeout') !== -1) {
// 超时导致的
MessageBox.alert('请求超时,请检查接口是否异常或者网络不通');
} else {
// 其它错误,暂不细分,等出现再处理
MessageBox.alert('服务器异常,错误信息:' + err);
}
if(errorCatch) {
reject(err);
}
});
});
}
- 页面调用
import { mapActions } from 'vuex'
// 在method中引入方法
...mapActions([
'$ajax'
])
// this.$ajax({
data: {
'funcNo': '1000516',
'busi_type': '0',
'share_type': this.share_type,
'user_id': this.user_id,
'op_channel': 3
}
}).then(res => {
}.catch(err => {
// 只有当设置了errorCatch,才会调用该处
})