可通过全局计数器控制loading:计数为0时显示,归0时隐藏;用闭包封装避免污染全局;promise.finally确保成对增减;支持并发与防抖(如300ms最小显示时间)。

可以通过维护一个全局计数器,在每个异步操作开始时加 1、结束时减 1,当计数器从 0 变为 1 时显示 loading,从 1 变为 0 时隐藏 loading。关键在于确保增减操作成对、线程安全(JS 单线程但需防重复 resolve/reject 或多次 catch 导致计数错乱)。
用闭包封装计数器与状态控制
避免全局变量污染,推荐用模块化方式管理:
const globalLoading = (() => {
let count = 0;
const show = () => {
if (count === 0) {
document.body.classList.add('loading');
// 或操作 loading 元素:document.getElementById('global-loader').style.display = 'block';
}
count++;
};
const hide = () => {
if (count > 0) count--;
if (count === 0) {
document.body.classList.remove('loading');
// 或:document.getElementById('global-loader').style.display = 'none';
}
};
return { show, hide };
})();
包装 Promise 自动计数(推荐工具函数)
所有需要触发 loading 的异步调用都走统一包装函数,保证 start/end 成对:
- 用 Promise.finally() 确保无论成功失败都调用
hide() - 不依赖
.then().catch()分支,避免漏掉某条路径 - 示例封装:
function withLoading(promise) {
globalLoading.show();
return promise.finally(() => globalLoading.hide());
}
// 使用方式
withLoading(fetch('/api/data'))
.then(res => res.json())
.then(data => console.log(data));
处理并发 Promise(如 Promise.all)
多个请求同时发起时,计数器天然支持并发:每个 promise 独立调用 show 和 finally → hide,总数自动叠加与归零。
-
Promise.all([p1, p2, p3])会触发 3 次show,后续各自完成时各减 1 - 即使部分失败,
finally仍执行,计数准确 - 若想「只要有一个 pending 就保持 loading」,当前逻辑已满足;无需额外处理
进阶:防抖隐藏 & 忽略短时请求
避免 loading 闪现,可给 hide 加最小显示时间(如 300ms):
let hideTimer = null;
const hide = () => {
if (count > 0) count--;
if (count === 0) {
clearTimeout(hideTimer);
hideTimer = setTimeout(() => {
if (count === 0) {
document.body.classList.remove('loading');
}
}, 300);
}
};
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











