RT.
Vue项目,封装了一层axios,只要调用axios就出现loading,然后在axios响应拦截器处让loading消失,这就导致了第一个请求完成后loading消失,后面的请求pending半天,用户总是感觉没数据,觉得现在唯一的办法是得知最后一个请求的状态
RT.
Vue项目,封装了一层axios,只要调用axios就出现loading,然后在axios响应拦截器处让loading消失,这就导致了第一个请求完成后loading消失,后面的请求pending半天,用户总是感觉没数据,觉得现在唯一的办法是得知最后一个请求的状态
// 伪代码
showLoading();
const loads = urls.map(url => ajax(url));
await Promise.all(loads);
hideLoading();
2023-02-22 更新
今天又看到这个问题,补充个合并 loading 的示例
const { mockRemote, wrapLoading } = (() => {
let loading = false;
function mockRemote(tag, ms) {
return new Promise(resolve => setTimeout(
() => {
console.log(`${tag} ${ms} ${Date.now() % 100000}`);
resolve(ms);
},
ms)
);
}
async function wrapLoading(fn) {
if (loading) {
return await fn();
}
loading = true;
const mark = Date.now();
console.log(`[${mark}] loading`);
try {
return await fn();
} finally {
console.log(`[${mark}] loaded`);
}
}
return { mockRemote, wrapLoading };
})();
const b1 = async () => await mockRemote("b1", 1000);
const b2 = async () => await wrapLoading(() => mockRemote("b2", 500));
const b3 = async () => await mockRemote("b3", 800);
console.log("----------------------------");
console.log("testing single loading");
console.log("----------------------------");
await b2();
console.log("----------------------------");
console.log("testing merge lading");
console.log("----------------------------");
await wrapLoading(async () => {
await b1();
await b2();
await b3();
});
比较好的方式是全局统一拦截器,js是单线程的,所以使用一个变量记录下当前进行中的请求
let requestingCount = 0;
const handleRequestLoading = () => {
if (!requestingCount) startLoading()
requestingCount++
}
const handleResponseLoading = () => {
requestingCount--
if (!requestingCount) stopLoading()
}
axiosInstance.interceptors.request.use(config => {
handleRequestLoading()
},() => {
handleResponseLoading()
})
axiosInstance.interceptors.response.use(response => {
handleResponseLoading()
}, error => {
handleResponseLoading()
})
方案1. 七个请求做成队列,第一个完成再请求第二个。以此类推直到最后一个结束
方案2. 七个请求任意一个完成之后检查当前完成数(可以是简单的计数),如果满七干嘛干嘛,否则啥都不干
现在流行的 Promise 也可以,不过暂时不会用
let p1 = new Promise((resolve, reject) => {
resolve(1);
})
let p2 = new Promise((resolve, reject) => {
resolve(2);
})
let p3 = new Promise((resolve, reject) => {
resolve(3);
})
Promise.all([p1, p2, p3]).then(values => {
console.log(values);
});
官方例子:
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
// Both requests are now complete
}));
6 回答3.1k 阅读✓ 已解决
6 回答2.5k 阅读
5 回答6.5k 阅读✓ 已解决
2 回答2k 阅读✓ 已解决
2 回答1.6k 阅读✓ 已解决
2 回答1k 阅读✓ 已解决
3 回答1.8k 阅读✓ 已解决
非常感谢大家的解答,现在已经解决,自答一下,如果有更好的方法希望大家分享一下,谢谢