前端性能优化——对节流与防抖的理解
节流(throttling)和防抖(debouncing)是两种常用于优化前端性能和处理事件频繁触发的技术
1.节流(Throttling):
- 节流是指在一定时间间隔内只执行一次操作。它适用于需要控制执行频率的场景,如滚动事件、resize事件等。(函数节流是指规定一个单位时间,在这个单位时间内,只能有一次触
发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。节流可以使用在 scroll 函数的事件监听上,通过事件节流来降低事件调用的频率。) - 使用场景:
拖拽场景:固定时间内只执⾏⼀次,防⽌超⾼频次触发位置变动
缩放场景:监控浏览器 resize
动画场景:避免短时间内多次触发动画引起性能问题 - 举例:假设有一个滚动事件监听,当用户滚动页面时会触发更新操作。通过节流,可以设置在每隔200ms执行一次更新操作,而不是每次滚动都执行,从而减少操作频率,提升性能。
function throttle(func, delay) {
let timer = null;
return function() {
if (!timer) {
timer = setTimeout(() => {
func.apply(this, arguments);
timer = null;
}, delay);
}
}
}
window.addEventListener('scroll', throttle(handleScroll, 200));
//这段代码定义了一个名为throttle的函数,它接受两个参数:一个是需要节流的函数func,另一个是延迟
//时间delay。这个函数的目的是限制func在指定的延迟时间内只能执行一次,即使func被多次调用。
//具体来说,throttle函数内部创建了一个名为timer的变量,用于存储定时器的引用。然后返回一个新的函
//数,这个新函数在每次调用时会检查timer是否存在。如果timer不存在,说明没有正在等待执行的定时器,
//那么就设置一个新的定时器,延迟delay毫秒后执行func,并将timer设置为null。如果timer已经存在,
//说明上一次的定时器还没有执行,那么这次调用就会被忽略,不会触发func的执行。
//最后一行代码是将handleScroll函数作为参数传递给throttle函数,并设置了200毫秒的延迟时间。这意味
//着handleScroll函数最多每200毫秒只会被执行一次,即使在滚动事件频繁触发的情况下。这样可以有效地
//减少浏览器的性能开销,提高页面的滚动性能
2.防抖(Debouncing):
- 防抖是指在事件触发后等待一定时间再执行操作,若在此期间再次触发事件,则重新计时。它适用于需要确保事件在停止触发一段时间后再执行的场景,如搜索框输入、窗口调整大小等。(函数防抖是指在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。这可以使用在一些点击请求的事件上,避免因为用户的多次点击向后端发送多次请求。)
- 使用场景:
按钮提交场景:防⽌多次提交按钮,只执⾏最后提交的⼀次
服务端验证场景:表单验证需要服务端配合,只执⾏⼀段连续的输⼊
事件的最后⼀次,还有搜索联想词功能类似⽣存环境请⽤lodash.debounce - 举例:在一个输入框中实时搜索功能,用户输入时触发搜索操作,通过防抖可以确保用户停止输入后的一段时间内才执行搜索操作,避免频繁请求后端接口。
function debounce(func, delay) {
let timer = null;
return function() {
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, arguments);
}, delay);
}
}
const searchInput = document.getElementById('search-input');
searchInput.addEventListener('input', debounce(handleInput, 300));
//这段代码定义了一个名为debounce的函数,它接受两个参数:一个是需要去抖动的函数func,另一个是延迟
//时间delay。这个函数的目的是在指定的延迟时间内限制func只能执行一次,即使func被多次调用。
//具体来说,debounce函数内部创建了一个名为timer的变量,用于存储定时器的引用。然后返回一个新的函
//数,这个新函数在每次调用时会清除timer(如果存在)。接着,它会设置一个新的定时器,延迟delay毫秒
//后执行func。如果在这个延迟期间再次调用这个新函数,它会清除之前的定时器并重新设置,从而确保func
//在连续调用的情况下只执行一次。
//最后一行代码是将handleInput函数作为参数传递给debounce函数,并设置了300毫秒的延迟时间。这意味着
//handleInput函数在用户连续输入时最多每300毫秒只会被执行一次,即使在输入事件频繁触发的情况下。
//这样可以有效地减少浏览器的性能开销,提高页面的响应性能。