如何在 Fetch 请求期间正确显示加载动画(Preloader)

2次阅读

如何在 Fetch 请求期间正确显示加载动画(Preloader)

本文详解如何在使用 javascript fetch api 获取数据时,确保加载指示器(如旋转动画)能及时、可靠地显示与隐藏,重点解决因 css 选择器作用域错误导致的 preloader 不可见问题。

在基于 Fetch 的异步请求中,为提升用户体验,通常需在请求发起后立即显示加载动画(preloader),并在响应完成或出错后将其隐藏。但许多开发者会遇到“明明调用了 showLoad(),页面却看不到 loader”的情况——这往往并非逻辑错误,而是 css 样式优先级或选择器匹配失效所致。

在你提供的代码中,关键问题在于 CSS 类名绑定与样式定义不一致:

#load {   display: none; /* 初始隐藏 */ }  #load.display {   display: block; }

javaScript 中通过 loader.classList.add(‘display’) 添加的是类名 display,但该类仅在元素同时具有 id=”load” 拥有 class=”display” 时才生效。看似合理,实则存在隐患:若后续 html 结构微调(如 id 变更)、或 CSS 预处理器/框架引入更高优先级规则,#load.display 就可能被覆盖或失效。

✅ 正确做法是解耦 ID 与状态类,将显示控制权完全交由类名本身:

#load {   border: 5px solid #f3f3f3;   border-top: 5px solid #3498db;   border-radius: 50%;   width: 20px;   height: 20px;   animation: spin 2s linear infinite;   margin-left: 160px;   display: none; /* 默认隐藏 */ }  .display {   display: block !important; /* 强制生效,避免被其他样式覆盖 */ }  @keyframes spin {   0% { transform: rotate(0deg); }   100% { transform: rotate(360deg); } }

同时保持 javascript 不变(已正确):

function showLoad() {   loader.classList.add('display'); }  function hideLoad() {   loader.classList.remove('display'); }  function getWeather() {   showLoad(); // ✅ 立即触发显示    fetch(`http://api.weatherapi.com/v1/current.json?key=XXXXXXX&q=${input.value}&aqi=no`)     .then(response => {       if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);       return response.json();     })     .then(res => {       const celsius = `Temp ${res.current.temp_c} °C`;       divId.innerHTML = celsius;     })     .catch(err => {       console.error('Weather fetch failed:', err);       divId.innerHTML = 'Failed to load weather data.';     })     .finally(() => {       hideLoad(); // ✅ 无论成功或失败,都确保隐藏     }); }

⚠️ 关键优化点说明:

  • 使用 .finally() 替代仅在 .then() 中调用 hideLoad(),确保异常(如网络中断、jsON 解析失败、API 报错)时 loader 也能关闭,避免界面卡死在加载态;
  • 在 .display 规则中添加 !important 是防御性写法(尤其在复杂项目中),防止第三方样式或内联样式意外覆盖;
  • 建议为 fetch 添加 response.ok 校验,提升健壮性;
  • 若 loader 元素位于动态渲染区域,确保其 dom 节点在脚本执行前已存在(你当前代码中通过 getElementById(‘load’) 获取,符合要求)。

? 扩展建议:
如需支持多请求并发场景(例如用户快速点击多次),可增加防抖(debounce)或禁用按钮逻辑;对于更现代的方案,也可考虑使用

至此,preloader 将在每次点击搜索按钮后即时显现,并在数据就绪或出错后自动消失,真正实现“所见即所得”的加载反馈。

text=ZqhQzanResources