Mark24
JavaScript编程之防抖和节流
更新 2023年03月18日 追加概述
在编程中防抖 (debounce) 和节流 (throttle) 都是为了解决某些事件频繁触发,导致性能受到影响的问题。不过它们的策略略有不同:
防抖
防抖的原理是在触发事件后,设立一个等待时间,如果在等待时间内再次触发事件,则重新计时,直到等待时间结束后才执行事件。类比于现实中的抖动开关,如果频繁地切换开关状态,只有最后一个状态确定后才能执行对应的操作。
举个例子,当用户连续快速点击按钮时,防抖能够确保只有最后一个点击事件被触发,而前几次点击事件会被忽略。
节流
节流的原理是在设定时间内,无论事件触发了多少次,只执行一次事件。类比于现实中的自来水龙头,打开后持续流水时,为了避免水资源的浪费,在很短的时间段内,每隔一段时间就会流出一次水滴。
再举一个例子,当用户滚动滚动条时,节流能够确保每隔一定时间才执行一次处理逻辑,避免了处理逻辑的频繁触发。
因此,防抖和节流的策略不同,根据实际的使用场景,我们可以选择合适的策略来减少频繁事件的触发,提高代码的执行效率。
一个经典的比喻:
想象每天上班大厦底下的电梯。把电梯完成一次运送,类比为一次函数的执行和响应
假设电梯有两种运行策略 debounce 和 throttle,超时设定为15秒,不考虑容量限制
电梯第一个人进来后,15秒后准时运送一次,这是节流
电梯第一个人进来后,等待15秒。如果过程中又有人进来,15秒等待重新计时,直到15秒后开始运送,这是防抖
1.防抖 (debounce)
原理:
只以最后一次触发的时间为准,延迟n秒后才执行。如果延迟n秒的时间内又触发事件,则以新的事件为时间基准,延迟n秒再执行 应用场景:
登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖
调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖
文本编辑器实时保存,当无任何更改操作一秒后进行保存
简单代码:防抖重在清零 clearTimeout(timer)
function debounce(func, wait) {
var timeout;
return function () {
clearTimeout(timeout)
timeout = setTimeout(func, wait);
}
}
// 不断的调用 debounce(some_action, 1000)
// 以最后一次调用为准进行延迟
2.节流 (throttle)
原理:
控制事件发生的频率,如控制为1s发生一次,甚至1分钟发生一次 应用场景:
scroll 事件,每隔一秒计算一次位置信息等
浏览器播放事件,每个一秒计算一次进度信息等
input 框实时搜索并发送请求展示下拉列表,每隔一秒发送一次请求 (也可做防抖)
简单代码:节流重在开锁关锁 timer = setTimeout timer = null、nowTime - lastTime > wait
//1.设置定时器
function throttle(func, wait) {
var timeout = null;
return function() {
if (!timeout) {
timeout = setTimeout(function(){
timeout = null;
func()
}, wait)
}
}
}
//2.使用时间戳
function throttle2 (func, wait) {
let lastTime = 0;
return function () {
let nowTime = +new Date();
if (nowTime - lastTime > wait) {
func();
lastTime = nowTime
}
}
}
// 这里必须假象,在 某在场景比如 scroll中,这个函数被多次频繁调用
// 频繁调用的场景下思考这个函数才有意义
// 尤其是第二个时间辍方法,就是在频繁调用,他检查时间辍才有意义