在前端页面中,使用Fetch发起网络请求时,接口响应时间存在不确定性,若没有合适的反馈机制,用户很容易误以为页面卡顿。加载动画Preloader可以在请求发起时展示,请求结束无论成功失败都隐藏,给用户明确的操作反馈。

基础实现逻辑
核心思路是在Fetch请求发起前显示加载动画,在请求完成(包括成功和失败)后隐藏加载动画。我们可以通过操作DOM元素的显示状态来控制Preloader的显隐。
HTML结构准备
首先准备一个加载动画的容器,默认隐藏,请求时显示:
<!-- 加载动画容器 --> <div id="preloader" style="display: none;"> <div class="spinner"></div> <p>加载中,请稍候...</p> </div> <!-- 请求结果展示区域 --> <div id="result"></div> <button id="fetchBtn">发起请求</button>
基础JavaScript实现
通过控制preloader元素的display属性来切换显隐,注意要在finally回调中隐藏动画,确保无论请求成功失败都会执行:
// 获取DOM元素
const preloader = document.getElementById('preloader');
const result = document.getElementById('result');
const fetchBtn = document.getElementById('fetchBtn');
// 显示加载动画
function showPreloader() {
preloader.style.display = 'block';
}
// 隐藏加载动画
function hidePreloader() {
preloader.style.display = 'none';
}
// 绑定按钮点击事件
fetchBtn.addEventListener('click', () => {
// 请求发起前显示加载动画
showPreloader();
// 清空之前的结果
result.innerHTML = '';
// 发起Fetch请求
fetch('https://ipipp.com/api/test-data')
.then(response => {
if (!response.ok) {
throw new Error('接口响应异常');
}
return response.json();
})
.then(data => {
// 请求成功处理数据
result.innerHTML = `<p>请求成功,数据:${JSON.stringify(data)}</p>`;
})
.catch(error => {
// 请求失败提示错误
result.innerHTML = `<p>请求失败:${error.message}</p>`;
})
.finally(() => {
// 无论成功失败都隐藏加载动画
hidePreloader();
});
});
多请求场景的处理
如果页面同时存在多个Fetch请求,直接控制单个Preloader会出现问题:比如第一个请求还没结束,第二个请求发起就隐藏了动画,或者多个请求结束后提前隐藏动画。此时需要维护一个请求计数器。
计数器实现方案
每次发起请求计数器加1,请求结束计数器减1,只有当计数器为0时才隐藏加载动画:
let requestCount = 0;
const preloader = document.getElementById('preloader');
// 显示加载动画,计数器加1
function showPreloader() {
requestCount++;
preloader.style.display = 'block';
}
// 隐藏加载动画,计数器减1,只有计数器为0才隐藏
function hidePreloader() {
requestCount--;
if (requestCount <= 0) {
requestCount = 0;
preloader.style.display = 'none';
}
}
// 封装带加载动画的Fetch请求
function fetchWithPreloader(url, options) {
showPreloader();
return fetch(url, options)
.finally(() => {
hidePreloader();
});
}
// 多个请求同时发起的示例
document.getElementById('multiFetchBtn').addEventListener('click', () => {
// 第一个请求
fetchWithPreloader('https://ipipp.com/api/data1')
.then(res => res.json())
.then(data => console.log('请求1结果', data));
// 第二个请求
fetchWithPreloader('https://ipipp.com/api/data2')
.then(res => res.json())
.then(data => console.log('请求2结果', data));
});
注意事项
- 加载动画的样式可以根据需求自定义,比如旋转动画、进度条等,只要保证容器可以通过display属性控制显隐即可。
- 如果Fetch请求设置了超时时间,超时后也需要确保加载动画被隐藏,可以在超时处理的逻辑中调用hidePreloader。
- 若页面使用前端框架如Vue、React,可以将Preloader的显隐状态放到组件的状态中管理,配合请求拦截器统一处理,不需要每个请求单独写显隐逻辑。
- 不要在请求成功或失败的回调中单独隐藏动画,一定要放在finally中,避免异常情况下动画一直显示的问题。
常见问题解答
为什么加载动画有时候不消失?
最常见的原因是隐藏动画的逻辑没有放在finally回调中,或者请求过程中出现了未捕获的异常跳过了隐藏逻辑。另外多请求场景下没有用计数器管理,也会导致动画提前消失或一直显示。
可以在Preloader中显示请求进度吗?
Fetch本身不支持进度监听,如果需要显示上传或下载进度,可以使用XMLHttpRequest,或者将Fetch和ReadableStream结合实现,此时可以在加载动画中同步更新进度信息。
FetchPreloader加载动画JavaScript前端交互修改时间:2026-07-04 06:39:31