Skip to content
On this page

debounce 防抖函数

Hidden Title

基础用法:const debounced = debounce(fn, 500)

基础用法

说明

debounce 用于创建一个防抖函数,适合搜索输入、表单提交、窗口尺寸变化等高频事件。连续调用时会重新计时,默认在停止调用 500ms 后执行最后一次传入的参数;也可以通过 immediate 让第一次调用立即执行。

调用形式

ts
const debounced = debounce(fn)
const debounced = debounce(fn, delay)
const debounced = debounce(fn, delay, immediate)
const debounced = debounce(fn, delay, immediate, resultCallback)
const debounced = debounce(fn)
const debounced = debounce(fn, delay)
const debounced = debounce(fn, delay, immediate)
const debounced = debounce(fn, delay, immediate, resultCallback)

参数说明

参数类型必填可选值默认值说明
fn(...args: any[]) => any任意函数-需要防抖执行的函数。
delaynumber大于等于 0500防抖等待时间,单位毫秒。
immediatebooleantruefalsefalse是否在第一次调用时立即执行。
resultCallback(result) => void任意结果回调函数-每次 fn 真正执行后触发,参数是 fn 的返回值。

返回值

返回一个 Promise 风格的防抖函数,并带有 cancel() 方法:

返回内容说明
调用结果Promise<Awaited<ReturnType<typeof fn>>>,解析为函数结果。
cancel()取消等待中的执行,并重置立即执行状态。

常用场景

ts
const search = debounce((keyword: string) => {
  return keyword.trim()
}, 300)

const result = await search('sybz')

const submit = debounce(
  () => saveForm(),
  500,
  true,
  (result) => {
    console.log('提交结果:', result)
  },
)

submit()
submit.cancel()
const search = debounce((keyword: string) => {
  return keyword.trim()
}, 300)

const result = await search('sybz')

const submit = debounce(
  () => saveForm(),
  500,
  true,
  (result) => {
    console.log('提交结果:', result)
  },
)

submit()
submit.cancel()

注意事项

immediate=false 时,连续调用只会在停止触发后执行最后一次。设置为 true 后,第一次调用会立即执行,等待期间的后续调用仍会重新计时并在结束时执行最后一次。组件卸载或不再需要等待中的任务时,应调用 cancel() 清理定时器。

函数源码

debounce

来源:packages/utils/src/base.ts

/**
 * 创建防抖函数。
 *
 * @param func 需要防抖执行的函数。
 * @param delay 延迟时间,单位毫秒,默认 `500`。
 * @param immediate 是否在第一次调用时立即执行。
 * @param resultCallback 每次真正执行后触发的结果回调。
 * @returns 带 `cancel()` 方法的防抖函数。
 *
 * @example
 * const search = debounce((keyword: string) => {
 *   return keyword.trim()
 * }, 300)
 *
 * await search('sybz')
 *
 * @example
 * const submit = debounce(saveForm, 500, true, (result) => {
 *   console.log(result)
 * })
 *
 * submit.cancel()
 */
export function debounce<T extends Func>(
  func: T,
  delay: number = 500,
  immediate?: boolean,
  resultCallback?: (result: ReturnType<T>) => void,
): DebouncedFunction<T> {
  let timer: null | ReturnType<typeof setTimeout> = null
  let isInvoke = false
  const _debounce = function (this: ThisParameterType<T>, ...args: Parameters<T>) {
    return new Promise((resolve, reject) => {
      if (timer) clearTimeout(timer)
      if (immediate && !isInvoke) {
        try {
          const result = func.apply(this, args)
          if (resultCallback) resultCallback(result)
          resolve(result)
        } catch (e) {
          reject(e)
        }
        isInvoke = true
      } else {
        timer = setTimeout(() => {
          try {
            const result = func.apply(this, args)
            if (resultCallback) resultCallback(result)
            resolve(result)
          } catch (e) {
            reject(e)
          }
          isInvoke = false
          timer = null
        }, delay)
      }
    })
  } as DebouncedFunction<T>
  _debounce.cancel = function () {
    if (timer) clearTimeout(timer)
    isInvoke = false
    timer = null
  }
  return _debounce
}

思云博智私有前端组件库