跳到主要内容
全部已验证问答

你知道防抖吗,能实现一下吗?

作者已验证2026-08-14 · 回答由 AI 分身生成,作者本人盖章认可

知道。防抖(debounce)的核心是:事件频繁触发时不断重置计时器,直到停止触发超过指定时间,才执行最后一次回调。

它适合搜索联想、服务端表单校验,以及避免按钮连续点击重复提交;而 scroll、拖拽、resize 这类需要持续响应的高频事件,通常更适合节流【2】【3】【5】。

type Debounced<T extends (...args: any[]) => any> = {
  (...args: Parameters<T>): void;
  cancel: () => void;
};

function debounce<T extends (...args: any[]) => any>(
  fn: T,
  wait = 300
): Debounced<T> {
  let timer: ReturnType<typeof setTimeout> | undefined;

  function debounced(this: ThisParameterType<T>, ...args: Parameters<T>) {
    if (timer) clearTimeout(timer);

    timer = setTimeout(() => {
      timer = undefined;
      fn.apply(this, args);
    }, wait);
  }

  debounced.cancel = () => {
    if (timer) clearTimeout(timer);
    timer = undefined;
  };

  return debounced;
}

使用示例:

const search = debounce(async (keyword: string) => {
  const res = await fetch(`/api/search?q=${encodeURIComponent(keyword)}`);
  console.log(await res.json());
}, 300);

document.querySelector<HTMLInputElement>('#search')!
  .addEventListener('input', (event) => {
    search(event.currentTarget.value);
  });

如果用户连续输入,前面的定时器都会被取消;只有停下来 300ms 后,才会用最终的关键词发一次请求。

按钮提交时可以这样用:

const submit = debounce(() => {
  console.log('提交表单');
}, 500);

document.querySelector('#submit')!
  .addEventListener('click', submit);

不过我补充一点:防抖只能改善前端重复触发,不能代替服务端幂等控制。 对支付、创建订单等关键接口,后端仍应通过幂等键、唯一约束或状态机保证不会重复处理。

对这个话题还有疑问?

接着问分身