无限滚动节流改造后Loading提示不显示问题排查
无限滚动加载提示不显示问题排查与解决
问题描述
我正在实现一个无限滚动脚本,原代码可正常运行。为优化性能尝试添加节流技术,修改window.onscroll事件逻辑:滚动触底时先设置loading.innerHTML为“Loading...”,await延迟1秒后调用load函数,再清空loading内容。但实际运行时load函数可执行,“Loading...”却完全不显示,控制台无报错。
原代码
HTML
<div id="content"></div> <div id="loading"></div>
JavaScript
var page = 0, proceed = true, message; const load = () => { if (page < 10 && proceed) { proceed = false; fetch("", { body: "page=" + page, headers: { "Content-Type": "application/x-www-form-urlencoded" }, method: "POST" }) .then(res => res.ok ? res.json() : Promise.reject(res)) .then(res => { res.forEach(el => content.innerHTML += ...); page++; proceed = true; }); } }; window.onscroll = () => { var { scrollTop, scrollHeight, clientHeight } = document.documentElement; if (scrollTop + clientHeight >= scrollHeight - 5) load(); }; load();
修改后的滚动事件代码
const delay = time => new Promise(res => setTimeout(res, time)); window.onscroll = () => { var { scrollTop, scrollHeight, clientHeight } = document.documentElement; if (scrollTop + clientHeight >= scrollHeight - 5) { loading.innerHTML = "Loading..."; await delay(1000); load(); loading.innerHTML = ""; } };
问题根源
async关键字缺失:使用await的函数必须声明为async,你修改后的onscroll回调未添加该关键字,导致浏览器无法识别await,会同步执行所有代码——瞬间完成loading.innerHTML的设置与清空,因此看不到加载提示。- 未结合原有节流逻辑:滚动事件会高频触发,即使修复
async问题,若不通过proceed变量控制,会多次触发加载流程,导致loading内容被频繁覆盖;同时load函数是异步的,延迟1秒后调用load就立刻清空loading,会导致提示在数据加载完成前就消失。
解决方法
步骤1:给滚动回调添加async关键字
确保await能正常工作,让代码按预期顺序执行。
步骤2:修改load函数返回Promise
让load支持await,确保等待数据加载完成后再清空加载提示。
步骤3:复用proceed变量做节流
避免滚动事件重复触发加载逻辑,同时在加载完成(或出错)后解锁。
修正后的完整代码
调整后的load函数
const load = () => { return new Promise((resolve, reject) => { if (page < 10) { fetch("", { body: "page=" + page, headers: { "Content-Type": "application/x-www-form-urlencoded" }, method: "POST" }) .then(res => res.ok ? res.json() : Promise.reject(res)) .then(res => { res.forEach(el => content.innerHTML += ...); page++; resolve(); }) .catch(err => { console.error("加载失败:", err); reject(err); proceed = true; // 出错时解锁,允许后续加载 }); } else { resolve(); } }); };
调整后的滚动事件
const delay = time => new Promise(res => setTimeout(res, time)); window.onscroll = async () => { const { scrollTop, scrollHeight, clientHeight } = document.documentElement; if (scrollTop + clientHeight >= scrollHeight - 5 && proceed) { proceed = false; loading.innerHTML = "Loading..."; await delay(1000); // 可选延迟,若不需要可删除 try { await load(); loading.innerHTML = ""; } finally { proceed = true; // 无论成功失败都解锁 } } };
额外说明
- 若不需要刻意的1秒延迟,可直接删除
await delay(1000),避免不必要的等待,提升用户体验。 - 原代码中的
proceed变量是核心节流控制,修改时务必保留,防止滚动事件频繁触发加载请求。
内容的提问来源于stack exchange,提问作者AbsoluteBeginner
相关产品推荐
相关产品推荐

