效果图:

封装包括
1.多个请求使用唯一Loading的处理。
2.网络超时的处理。
3.断网情况下的处理。
4.去除重复请求(这个单独放在了一个文件中,不常用)
注意:
本文使用的版本为"axios": "0.18.1" 目前最新的0.19.0不支持config的配置,所以如果是新加进入的axios库你需要检查一下版本号。
1.多个请求使用唯一Loading的处理。
理解
1.先思考如果这个时候有多个连续的请求那么这些请求会执行哪些方法?(最好搞个for循环请求一个接口看下log都跑了哪些方法)
2.在触发一个请求时一定会先执行request拦截器的config() ,然后如果请求成功再执行响应拦截器中的response() 如果请求失败会执行响应拦截器中的error()。
3.我们可以依据这个规律创建一个全局变量,每次进入请求拦截器时+1,每次退出拦截器时-1。如果这个全局变量>0那么就让这个Loading一直显示,否则将Loading关闭。
4.优化:不是每个请求都需要loading,所以在上面的基础上加一层是否需要showLoading的判断。
①需要配置config 该请求是否需要Loading
//showLoading 这里默认不loading 如果需要展示传入 {showLoading: true}
export function post(url, data = {}, config = {showLoading: false}) {
return new Promise((resolve, reject) => {
axios
.post(url, data, config)
.then(response => {
resolve(response.data);
})
.catch(err => {
reject(err);
});
});
}
②请求拦截
/*请求拦截*/
axios.interceptors.request.use(
async function(config) {
if (config.showLoading) {
showFullScreenLoading();
}
return config;
},
error => {
return Promise.reject(error);
},
);
③响应拦截
/*请求响应拦截*/
axios.interceptors.response.use(
response => {
...
if (response.config.showLoading) {
tryHideFullScreenLoading();
}
return response;
},
error => {
...
if (error.config.showLoading) {
tryHideFullScreenLoading();
}
Loading.hide();
...
return Promise.reject(errorMsg);
},
);
④控制全局变量的中间操作
/*请求合并只出现一次loading*/
let needLoadingRequestCount = 0;
function showFullScreenLoading() {
if (needLoadingRequestCount === 0) {
loading('start'); /*loading加载*/
}
needLoadingRequestCount++;
}
function tryHideFullScreenLoading() {
if (needLoadingRequestCount <= 0) return;
needLoadingRequestCount--;
if (needLoadingRequestCount === 0) {
setTimeout(tryCloseLoading, 300); /*300ms 间隔内的 loading 合并为一次*/
}
}
const tryCloseLoading = () => {
if (needLoadingRequestCount === 0) {
loading('end'); /*loading加载*/
}
};
/*loading加载*/
function loading(str) {
if (str == 'start') {
Loading.show();
} else if (str == 'end') {
Loading.hide();
}
}
对error 的处理
首先需要明确一点我们什么时候需要对error进行处理。我想实际的开发工程中只有两点
1.当有响应数据时,响应的status 返回的值不是约定的success(比如我们约定的是status = 1,但这时不是1)这时需要对error进行处理
2.网络异常的时候。(这里有两种 1️⃣网络超时,2️⃣网络断开连接)
其余的一些系统报出的异常一般情况下是不需要处理的。
先看下面裸体代码再讲 网络超时的处理和断网情况下的处理。
/*请求拦截*/
axios.interceptors.request.use(
async function(config) {
console.log('------------------------request');
return config;
},
error => {
console.log('------------------------request error ',error);
return Promise.reject(error);
},
);
/*请求响应拦截*/
axios.interceptors.response.use(
response => {
console.log('------------------------response');
return response;
},
error => {
console.log('------------------------response error',error);
return Promise.reject(error);
},
);
操作步骤
1.首先需要将config.timeout 设置的特别小比如config.timeout = 2
2.设置好后重启app请求查看log

下面图中的的log来源:console.log('------------------------response error',error);


3.查看log会发现“ 网络超时”时_timedOut:true
4.断网时 response: undefined,
根据上面的条件我们可以对响应拦截中的error进行如下处理
/*请求响应拦截*/
axios.interceptors.response.use(
response => {
....
return response;
},
error => {
....
var errorMsg;
const {response,request} = error;
if(response){//response 这里是对对接口响应不是约定的success进行处理
errorMsg=error
}else if(request._timedOut){
errorMsg="网络超时"
}else {
errorMsg="网络异常"
}
return Promise.reject(errorMsg);
},
);
网友评论