最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
节流:闭包实现固定时间频率限制逻辑
时间:2026-06-19 09:47:52 编辑:袖梨 来源:一聚教程网
节流函数必须用闭包封装lastTime和timer状态以实现隔离;时间戳版保频、首次立即执行,适合scroll/resize;定时器版收尾、只执行最后一次,适合搜索/防抖;增强版支持leading/trailing且共用闭包状态;视觉场景优先用requestAnimationFrame。
节流函数要真正实现“固定时间频率限制”,闭包不是可选项,而是必需结构——它把 lastTime 或 timer 这类状态牢牢锁在独立作用域里,既不被外部干扰,也不与其他节流实例冲突。
为什么必须用闭包封住状态
节流不是简单加个 setTimeout 就完事。它需要两个关键状态持续存在:
- lastTime:记录上一次真实执行的时间戳,用于判断是否过了间隔期
- timer:保存当前待执行的定时器 ID,用于清除旧任务、避免重复触发
这两个值不能每次调用都重置,也不能放在全局变量里——否则两个滚动监听器会互相覆盖 timer,或者 resize 和 scroll 共享一个 lastTime 导致节奏错乱。闭包让 throttle(fn, 100) 每次调用都生成专属上下文,状态彼此隔离。
时间戳版:保频型,适合滚动/缩放等稳定采样
逻辑是“首次立刻执行,之后只在间隔达标时再放行”。它不依赖定时器,响应直接,无延时偏差。
- 每次触发读取
Date.now(),与lastTime做差值判断 - 满足
now - lastTime >= delay才执行回调,并更新lastTime - 适合 scroll、resize、mousemove 等需“至少每 X 毫秒响应一次”的场景
定时器版:收尾型,适合输入搜索/加载更多
逻辑是“每次触发都重设延迟任务,最终只执行最后一次”。它靠 clearTimeout + setTimeout 协同工作。
- 首次触发设定时器,delay 后执行
- 期间重复触发,先
clearTimeout(timer),再设新定时器 - 执行回调后必须清空
timer = null,防止残留状态干扰下一轮 - 适合输入框搜索、按钮防连点、滚动到底部加载更多等“松手后才响应”的需求
带 leading/trailing 的增强版:首尾可控,仍靠闭包统一管理
业务常需要更精细控制:拖拽要立刻动(leading),松手后还要补一次加载(trailing)。这不能靠拼凑逻辑,必须由同一闭包维护全部状态。
-
leading: true→ 首次调用立即执行,并更新lastTime -
trailing: true→ 每次调用都尝试设定时器,但只保留最后一个 - trailing 回调里要二次判断:
if (Date.now() - lastTime >= delay),避免和 leading 冲突 -
timer、lastTime、pending标志位全在同一个闭包内闭环流转
进阶建议:视觉场景优先用 requestAnimationFrame
如果目标是 DOM 更新流畅(比如吸顶、视差滚动、懒加载),硬写 throttle(fn, 16) 不如用 RAF 闭包:
- 闭包内维护
isQueued = false,确保同一帧只注册一次requestAnimationFrame - 滚动事件里只做数据采集(如缓存 scrollTop),RAF 回调里再批量更新 DOM
- 天然对齐浏览器刷新节奏,比固定 delay 更稳定、更省资源
相关文章
- 商汤日日新开发者免费使用:模型选择、令牌额度与调用说明 06-19
- 2026拼图游戏app哪些值得下载 质量高的拼图游戏app大全 06-19
- 米姆米姆哈id是否能重复 06-19
- 商汤日日新开发者注册与登录:账号配置与权限说明 06-19
- 商汤日日新开发者账号权限:配置要点与适用范围 06-19
- 商汤日日新开发者入口在哪?Token领取与API权限配置说明 06-19