实现带取消功能的防抖函数需在返回函数上挂载cancel方法,通过闭包保存定时器ID并用clearTimeout清除;cancel需判空防误清,执行后重置timer为null。

实现带取消功能的防抖函数,关键是在返回的防抖函数上挂载一个 cancel 方法,用于清除待执行的定时器。这样调用者可在时机合适时主动中断延迟执行。
基础防抖结构 + 可取消能力
标准防抖会在最后一次触发后等待指定时间再执行;加入取消能力,只需把 setTimeout 的返回值(即定时器 ID)保存下来,并提供一个方法调用 clearTimeout。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 使用闭包保存定时器引用,避免外部直接访问或污染
-
cancel方法需判断定时器是否存在,防止重复清除报错 - 执行后应重置定时器引用,保证后续调用逻辑正确
代码实现(含注释)
function debounce(func, delay) {
let timer = null;
const debounced = function(...args) {
// 每次触发先清除前一次定时器
if (timer !== null) {
clearTimeout(timer);
}
// 设置新定时器
timer = setTimeout(() => {
func.apply(this, args);
timer = null; // 执行完清空引用
}, delay);
};
// 挂载取消方法
debounced.cancel = function() {
if (timer !== null) {
clearTimeout(timer);
timer = null;
}
};
return debounced;
}
使用示例
const handleSearch = debounce((query) => {
console.log('发起搜索:', query);
}, 300);
// 触发几次
handleSearch('a');
handleSearch('ab');
handleSearch('abc'); // 只有这次会最终执行
// 在执行前手动取消
handleSearch.cancel(); // 不会再输出 '发起搜索: abc'
// 也可在组件卸载、表单重置等场景调用 cancel
进阶:支持立即执行 + 取消
若需要“首次立即执行,后续仍防抖”,且支持取消已启动的延时部分,逻辑稍复杂:
- 需区分「立即执行阶段」和「等待再次触发阶段」
-
cancel应能中止等待中的延迟调用,但不影响已执行的立即调用 - 通常建议拆分为两个独立函数(
debounce和throttle)或使用成熟库如 Lodash 的debounce(它原生支持cancel和flush)

















