节流函数应用于无限滚动时仅限制“是否该加载”的判断频率,不直接控制请求;需配合状态锁与距离阈值保障真实加载,避免高频滚动下的冗余计算。

节流函数在无限滚动中不能直接用来控制加载请求,而应聚焦于“检测时机”的频率限制——即只让判断“是否该加载”的逻辑按固定节奏执行,真正的加载动作必须由状态锁和距离阈值双重保障。
节流只负责轻量判断,不碰网络请求
滚动事件每秒可能触发数十次,若每次都在里面计算 scrollHeight、scrollY 和加载条件,会造成大量无意义运算。节流的作用就是把这类计算压缩到每 150–200ms 最多一次:
- 用节流包裹距离判断逻辑(如 document.documentElement.scrollHeight - window.scrollY )
- 节流函数内部不做 fetch、不改 DOM、不触发渲染,只返回 true/false
- 加载函数 loadMore() 必须独立存在,且由节流后的判断结果+状态锁共同触发
必须搭配 loading 状态锁,防止重复请求
即使节流了判断频率,用户快速滚动仍可能在单次节流窗口内多次满足“接近底部”条件。此时仅靠节流无法阻止重复调用,必须引入显式状态控制:
- 声明 let loading = false 全局或闭包变量
- loadMore() 开头加 if (loading) return,立即拦截重复进入
- 发起请求前设 loading = true,请求结束(无论成功失败)再设 loading = false
- 这个锁是硬性闸门,节流只是减少它被频繁撞击的次数
距离阈值要预留缓冲区,避免临界卡顿
不能等到真正滚动到底部才触发加载,否则用户会看到空白或加载提示停留过久。合理设置提前加载距离:
立即学习“Java免费学习笔记(深入)”;
- 推荐用 window.innerHeight + 200px 作为触发阈值(可视区高度 + 预留缓冲)
- 避免写死像素值,可动态计算:比如取卡片平均高度 × 2,更适配不同列表结构
- 如果页面有吸顶导航栏,需从 window.scrollY 中减去其高度,否则判断会偏移
完整实现示例(无依赖,可直用)
以下代码整合节流、状态锁与距离判断,已剔除常见陷阱:
let loading = false;
<p>function throttle(func, delay) {
let lastCall = 0;
return function(...args) {
const now = Date.now();
if (now - lastCall >= delay) {
func.apply(this, args);
lastCall = now;
}
};
}</p><p>function shouldLoadMore() {
const { scrollHeight, scrollTop } = document.documentElement;
const windowHeight = window.innerHeight;
const threshold = windowHeight + 200;
return scrollHeight - scrollTop <= threshold;
}</p><p>function loadMore() {
if (loading) return;
loading = true;
fetch('/api/items?offset=...')
.then(res => res.json())
.then(data => {
// 渲染新数据
appendItems(data);
})
.finally(() => loading = false);
}</p><p>const checkAndLoad = throttle(() => {
if (shouldLoadMore()) loadMore();
}, 150);</p><p>window.addEventListener('scroll', checkAndLoad);</p>


















