防抖和节流
防抖
- 防抖的原理:你尽管触发事件,但是我一定在事件触发的n秒之后才执行,如果你在触发事件n秒内又触发了这个事件,那我就以新的事件的时间为准,n秒之后在执行。
节流
- 节流的原理: 如果你持续触发事件,每隔一段时间,只会执行一次事件
- 根据首次是否执行以及结束后是否执行,效果有所不同。
- 一般有两种主流的实现方式,一种是使用事件戳,一种是设置定时器
防抖
思路: 在第一次触发事件时,不立即执行函数,而是给出一个期限值比如200ms
- 如果在200ms内没有再次触发滚动事件,那么就执行函数。
- 如果在200ms内再次触发滚动事件,那么当前击时取消,重新开始计时。
效果: 如果短时间内触发同一个事件,只会执行一次函数
节流
效果: 如果短时间内触发一个事件,那么在执行回调函数完毕后,那么回调函数在指定时间内是不能触发的,直到过了这个时间段才可以触发.
防抖(debounce)
概念:防抖是指当持续触发事件时,一定时间段内没有再触发事件,事件处理函数执行一次,如果设定时间到来事件函数执行之前,又触发了该事件,就重新开始计时。也就是说当一个用户一直触发这个函数,且每次触发函数的间隔小于既定时间,那么在防抖的情况下只会执行一次。
解释:在防抖的情况下,当用户在短时间内频繁触发一个事件,该事件不会执行很多次,它只会执行一次。
节流(throttle)
概念:节流是指动作绑定事件后,动作触发事件,在这段时间内,如果动作又发生,则无视该动作,直到事件执行完后,才能重新触发。
1、
防抖:比如你在百度搜索框输入内容,然后弹出联想词。弹出联想词一般是你在输入完成后再过一会执行的,翻译成程序语言就是:keyup事件结束后一段时间(n秒)才触发,如果n秒内keyup事件又发生了,就重新计算时间。
用一句话概括为:将多次执行变为最后一次执行。
节流:比如你去高铁排队过安检,当人流高峰期时,一般会有个人拿个牌子,一次只放一部分人进去,这样做就是为了防止一段时间人流过大导致踩踏现象;再比如QQ网页版,当你上线后,你的好友是一部分一部分加载出来的,如果一下子加载所有的好友(比如几百个),那浏览器内存很容易被dom给撑死,但一次加载一部分就没事,因此我们用程序语言描述就是:某事件高频触发,但在 n 秒内只会执行一次,这样就会稀释函数的执行频率。
一句话总结:
节流是限制流量,点击次数再多,短时间内有效的也只有一次;防抖是防止手抖,连续多点了几次,也只是最后一次有效。
微信群中有人这么说:节流就跟怀孕一样,一段时间内只能怀一胎;防抖就跟下班一样,只要有新活儿来就不能走。
上边 Codepen 中节流和防抖的可视化演示,可能有助于理解,移动鼠标或滑动手指(移动端)开始执行节流和防抖
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <style> body { height: 2000px; } </style> </head> <body> <script> // 防抖 function debounce(fn, wait) { var timeout = null; return function () { if (timeout !== null) clearTimeout(timeout); timeout = setTimeout(fn, wait); }; } // 处理函数 function handle() { console.log(Math.random()); } // 滚动事件 window.addEventListener("scroll", debounce(handle, 1000));
//当持续触发scroll事件时,事件处理函数handle只在停止滚动1000毫秒之后才会调用一次,也就是说在持续触发scroll事件的过程中,事件处理函数handle一直没有执行。 </script> </body> </html>
使用场景
-
用户可能连续点击时使用节流
-
API 调用时使用节流
-
mousemove 或 touchmove 事件回调时使用节流
-
resize 事件回调时使用防抖
-
scroll 事件回调时使用防抖
-
一个自动保存功能中,保存函数使用防抖
防抖简单的理解就是,取消了前面的操作,只执行最后一次操作。
节流是指只执行第一次操作,取消后面的操作。
设置时间间隔为100ms,然后频繁触发touchmove,那么节流应该每100ms执行一次,而防抖是在100ms内频繁触发会清空定时器。
防止抖动应该是:图片加载的时候,可能会因为其它不确定因素(例如网络不稳定等),无法瞬间加载到图片,即无法马上撑开图片的空间,而是一截一截显示出来,这样就会导致后面的元素无法正常排版,出现抖动的情况。所以在最初,打算使用div去先撑开图片的空间。
1、函数防抖和节流,都是控制事件触发频率的方法。
2、函数防抖,这里的抖动就是执行的意思,而一般的抖动都是持续的,多次的。假设函数持续多次执行,我们希望让它冷静下来再执行。也就是当持续触发事件的时候,函数是完全不执行的,等最后一次触发结束的一段时间之后,再去执行。触发事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。
3、节流的意思是让函数有节制地执行,而不是毫无节制的触发一次就执行一次。节流就是保证一段时间内只执行一次核心代码。事件触发时,在n秒内只会执行一次,所以节流会稀释函数的执行频率。