实现JavaScript节流函数
function throttle(func, wait, options = {}) {
let timeout;
let previous = 0;
return function() {
const context = this;
const args = arguments;
const now = new Date().getTime();
if (!previous && options.leading === false) previous = now;
const remaining = wait - (now - previous);
if (remaining <= 0) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
func.apply(context, args);
} else if (!timeout && options.trailing!== false) {
timeout = setTimeout(() => {
previous = options.leading === true? 0 : new Date().getTime();
func.apply(context, args);
timeout = null;
}, remaining);
}
};
}
边界情况说明
- 立即执行(leading):当
options.leading === true
(默认情况) 时,函数会在开始时立即执行一次。如果 options.leading === false
,函数会在等待时间 wait
后执行。
- 最后一次执行(trailing):当
options.trailing === false
时,在节流结束时不会执行函数。默认情况下,options.trailing === true
,即在等待时间结束后会执行一次函数。
高并发场景下的性能问题及优化方向
- 性能问题:
- 内存占用:在高并发场景下,频繁触发节流函数会导致定时器不断创建和销毁,增加内存开销。
- 函数延迟执行:如果节流时间间隔设置不当,可能会导致用户操作与实际响应之间产生明显延迟,影响用户体验。
- 优化方向:
- 减少定时器使用:可以考虑使用
requestAnimationFrame
替代 setTimeout
,因为 requestAnimationFrame
是由浏览器优化过的,更适合处理频繁的动画和交互场景。
- 自适应节流:根据实际场景动态调整节流时间间隔,比如根据用户操作频率或者设备性能来动态改变
wait
的值。
- 防抖与节流结合:对于某些场景,可以先使用防抖函数处理短时间内的高频触发,然后再使用节流函数控制执行频率,以达到更好的性能和用户体验。