前端全局loading通过拦截fetch或axios实现:用计数器控制显隐,请求开始+1、结束-1,避免闪烁;支持白名单跳过、手动启停及SSR兼容,核心是“有借有还”的资源管理。

在前端实现全局 loading 的请求代理,核心思路是拦截所有网络请求(如 fetch 或 axios),在请求发起时显示 loading,在响应返回(无论成功或失败)时隐藏 loading。关键在于避免重复触发、支持并发控制、防止 loading 误关闭,同时保持对业务代码的低侵入性。
劫持原生 fetch 实现全局 loading
重写 window.fetch 是最通用的方式,适用于所有调用 fetch 的地方(包括第三方库内部使用):
// 保存原始 fetch
const originalFetch = window.fetch;
<p>// 全局 loading 状态管理(示例用简单布尔值,实际可用 React Context / Pinia / Vuex)
let loadingCount = 0;
const showLoading = () => {
if (loadingCount === 0) {
document.body.classList.add('loading-active');
// 这里可触发 UI 组件显示(如自定义 loading 遮罩)
}
loadingCount++;
};</p><p>const hideLoading = () => {
loadingCount = Math.max(0, loadingCount - 1);
if (loadingCount === 0) {
document.body.classList.remove('loading-active');
}
};</p><p>// 替换 fetch
window.fetch = async function(...args) {
showLoading();
try {
const response = await originalFetch(...args);
return response;
} finally {
hideLoading();
}
};✅ 优点:零配置、全站生效;❌ 注意:需确保页面初始化早于其他脚本执行(建议放在 <head> 中或使用 type="module" 控制顺序)。
封装 axios 并统一注入 loading 逻辑
若项目已用 axios,推荐通过请求/响应拦截器实现,更可控、易调试:
立即学习“Java免费学习笔记(深入)”;
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 用一个计数器(
loadingCount)跟踪待处理请求数,避免嵌套请求导致 loading 闪退 - 在
request interceptor中递增计数并显示 loading - 在
response interceptor和error interceptor中统一递减并隐藏 loading(必须两者都处理,否则请求报错时 loading 不会消失) - 可加白名单机制:对某些接口(如上传进度、心跳检测)跳过 loading
示例:
import axios from 'axios';
<p>let loadingCount = 0;</p><p>const startLoading = () => {
if (loadingCount === 0) {
// 触发全局 loading 显示(例如 dispatch action 或调用 UI 库方法)
showGlobalLoading();
}
loadingCount++;
};</p><p>const endLoading = () => {
loadingCount = Math.max(0, loadingCount - 1);
if (loadingCount === 0) {
hideGlobalLoading();
}
};</p><p>axios.interceptors.request.use(
config => {
// 可选:跳过特定请求
if (config.metadata?.noLoading) return config;
startLoading();
return config;
},
error => {
endLoading();
return Promise.reject(error);
}
);</p><p>axios.interceptors.response.use(
response => {
endLoading();
return response;
},
error => {
endLoading();
return Promise.reject(error);
}
);支持手动控制与局部禁用
实际业务中常需要「某个按钮点击时不显示 loading」或「手动开启/关闭」,可在请求配置中扩展字段:
- axios 场景:利用
config.metadata或自定义字段如showLoading: false - fetch 场景:在
init对象中传入{ noLoading: true },并在代理中读取 - 暴露全局函数如
startGlobalLoading()/stopGlobalLoading(),供特殊场景(如表单提交前预加载)手动调用
注意事项与避坑点
- 竞态问题:多个快速请求一发一收,可能导致 loading 闪烁——务必用计数器而非布尔值控制显隐
-
错误未捕获:fetch 默认不因 HTTP 状态码(如 404/500)reject,需手动检查
response.ok;axios 则默认对非 2xx reject,更友好 -
CORS 或网络异常:fetch 在跨域失败或断网时会直接 reject,已在
finally或拦截器 error 分支中覆盖,无需额外处理 -
SSR 兼容:服务端无
window或document,代理代码需包裹在if (typeof window !== 'undefined')中
不复杂但容易忽略细节,关键是把 loading 状态当成资源来管理——有借有还,多进少出,自然稳当。

















