【JS】关于防抖和节流
本篇文章主要是参考的这位老哥的文章:浅谈 JS 防抖和节流。
防抖和节流严格算起来应该属于性能优化的知识,但实际上遇到的频率相当高,处理不当或者放任不管就容易引起浏览器卡死。
场景定义
先说一个常见的功能,很多网站会提供这么一个按钮:用于返回顶部。
这个按钮只会在滚动到距离顶部一定位置之后才出现,那么我们现在抽象出这个功能需求 – 监听浏览器滚动事件,返回当前滚条与顶部的距离。
1 | function showTop() { |
】但是这段代码一旦运行你就会发现,这个函数执行的频率太高了,点击一次键盘上的向下按钮甚至就会执行8-9次。
防抖(debounce)
针对上面的场景,首先提出第一种思路:在第一次触发函数的时候,不立即执行,而是给出一个延时,比如200ms,如果200ms内函数又被调用,则不执行函数且重新开始计时。
1 | function debounce(fn, delay){ |
最后给出防抖的定义:对于短时间内连续触发的事件,防抖的作用就是限制其在给定的时间内只执行一次。
节流(throttle)
继续思考,使用上面防抖的解决方案可能会导致一个问题:
如果有个用户闲着无聊,不停的滚动页面,导致一直在重新计时,但是产品又有个需求是即使用户不断滚动页面,也会在某个时间间隔之后给出反馈。(虽然这个需求我看起来相当的不合理,仅用来讨论问题)
实现方案可以是这样:借助setTimeout,加入一个valid位来表示是否是工作状态,如果不是工作状态,直接返回;反之,就设置一个setTimeout并且将valid设置为非工作状态。
代码实现可以如下:
1 | function throttle(fn, delay){ |
其他应用场景举例
平时开发中常遇到的情形
- 搜索框input事件,例如要支持实时搜索,这时候可以使用节流方案(间隔一段时间就必须查询相关内容),或者实现输入间隔大于某个值(如500ms),就当作用户输入完成,然后开始搜索。
- 页面resize事件,常见于需要做页面适配的时候。需要根据最终呈现的页面进行dom渲染。(这个情形一般是使用防抖,因为只需要判断最后一次变化的情况。)