你在刷某电商网站时,输入框下方的搜索建议总能快速响应你的输入。但你有没有想过,如果每次敲击键盘都触发一次网络请求,不仅服务器压力大,页面也可能卡顿?这时候,防抖(Debounce)和节流(Throttle)就派上用场了。
防抖:让频繁操作只执行最后一次
防抖的核心思想是:在事件被触发 n 秒后才执行回调,如果在这 n 秒内又被触发,则重新计时。典型的应用场景就是搜索框的自动补全。
比如你在搜索“蓝牙耳机”,每输入一个字母都会触发 change 事件。使用防抖后,只有当你停止输入 300 毫秒后,才会真正发起请求,避免无效请求泛滥。
function debounce(func, delay) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
const searchInput = document.getElementById('search');
searchInput.addEventListener('input', debounce(function(e) {
console.log('发起搜索请求:', e.target.value);
}, 300));
节流:控制执行频率,匀速输出
节流则是保证一个函数在一定时间间隔内最多执行一次。即使事件持续触发,也按固定节奏执行。适合用于窗口滚动、鼠标移动这类高频但不需要实时响应的场景。
比如网页的“回到顶部”按钮,通常会在页面滚动一定距离后出现。如果不加控制,滚动过程中会频繁判断位置,浪费性能。使用节流后,每 100 毫秒检查一次即可。
function throttle(func, delay) {
let inThrottle;
return function (...args) {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => {
inThrottle = false;
}, delay);
}
};
}
window.addEventListener('scroll', throttle(function() {
const scrollTop = window.pageYOffset;
const topButton = document.getElementById('back-to-top');
if (scrollTop > 300) {
topButton.style.display = 'block';
} else {
topButton.style.display = 'none';
}
}, 100));
选择合适的策略
防抖适合那些只需要最终结果的操作,比如搜索、表单验证、自动保存。用户连续输入时,并不关心中间过程,只希望停顿后系统做出反应。
节流更适合需要周期性响应的场景,比如游戏中的按键检测、拖拽元素的位置更新、监控上报等。它像一个节拍器,让高频事件变得可控。
在实际开发中,React、Vue 等框架常配合 Lodash 的 debounce 和 throttle 方法使用,也可以自己封装 Hook 或指令来复用逻辑。
无论是防抖还是节流,本质都是对资源的尊重。减少不必要的计算和请求,不仅能提升用户体验,也能减轻服务器负担。在网络架构设计中,这类细节能有效缓解接口压力,提升系统稳定性。