防抖是在用户停止输入一段时间后才发起最后一次请求,核心是每次新输入清除旧定时器并重置倒计时。手写debounce函数需用clearTimeout和setTimeout管理定时器,调用时传入请求函数和延迟时间,并推荐结合AbortController取消未完成请求。

在输入框连续输入时用防抖合并请求,核心是:**只在用户停止输入一段时间后,才发起最后一次输入对应的请求**,避免每敲一个字就发一次请求。
防抖的基本逻辑
防抖(debounce)不是“限制频率”,而是“重置计时器”:每次有新输入,就清除上一次的定时器,重新开始倒计时。倒计时结束时执行请求,确保只响应最终稳定输入。
- 用户输入“hello”,过程中触发 5 次 input 事件 → 生成 5 个定时器,前 4 个都被 clearTimeout 清除
- 最后一次输入后,等待设定时间(如 300ms)无新输入 → 执行请求,参数是“hello”
- 关键:请求函数必须被包裹进防抖函数,且 input 事件里只调用这个包装后的函数
手写一个轻量防抖函数
不需要引入 Lodash,几行代码就能实现:
function debounce(fn, delay) {
let timer = null;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
使用示例:
const search = debounce((keyword) => {
fetch(`/api/search?q=${encodeURIComponent(keyword)}`)
.then(res => res.json())
.then(data => renderResults(data));
}, 300);
inputElement.addEventListener('input', (e) => {
search(e.target.value); // 每次输入都调用防抖后的 search
});
注意取消未完成的请求(可选但推荐)
如果用户快速输入“react”→“redux”→“rxjs”,前两个请求可能还在 pending 中。为避免旧请求干扰结果或浪费资源,可在发起新请求前取消上一个:
- 用 AbortController(现代浏览器支持)
- 把 controller 实例存在闭包或变量中,每次新请求前调用
abort() - 注意:fetch 的
signal要传入,且服务端需支持中断(一般不影响,只是前端不再监听响应)
常见坑与建议
防抖容易写错,尤其在闭包和 this 上:
- 别在 input 事件里直接写
setTimeout—— 容易漏 clearTimeout 或闭包引用旧值 - 防抖函数返回的是新函数,要提前定义并复用,不要每次 input 都重新创建
- 空字符串或空白输入是否请求?建议加判断:
if (!keyword.trim()) return; - 延迟时间选 200–500ms:太短(100ms)易误触发;太长(1s)影响体验
不复杂但容易忽略细节,重点是定时器管理干净、请求参数准确、旧请求及时清理。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











