Skip to content

debounce

防抖函数:高频触发 → 延迟执行,只执行最后一次

引入版本

0.25.0

Demo

ts
import { debounce } from '@wyfex/iutils'

/**
 * ================== 基础功能测试(延迟执行,不立即触发) ==================
 * 目的:验证防抖函数最后一次触发后延迟执行。
 */
let count1 = 0
const fn1 = () => count1++
const debouncedFn1 = debounce(fn1, 200)

// 连续触发 3 次
debouncedFn1()
debouncedFn1()
debouncedFn1()
// 立即执行:count = 0
// 200ms 后:count = 1(只执行最后一次)

/**
 * ================== immediate = true 立即执行模式 ==================
 * 目的:验证第一次触发立即执行,后续连续触发不执行,直到冷却结束。
 */
let count2 = 0
const fn2 = () => count2++
const debouncedFn2 = debounce(fn2, 200, true)

debouncedFn2() // 立即执行
debouncedFn2() // 忽略
debouncedFn2() // 忽略
// 立即执行:count = 1
// 200ms 内再次触发不执行
// 冷却结束后可再次立即执行

/**
 * ================== cancel () 取消测试 ==================
 * 目的:验证调用 cancel() 后定时器清空,函数不再执行。
 */
let count3 = 0
const fn3 = () => count3++
const debouncedFn3 = debounce(fn3, 200)

debouncedFn3()
debouncedFn3.cancel()
// 200ms 后:count = 0(未执行)
// isPending() = false

/**
 * ================== flush () 立即执行等待中的函数 ==================
 * 目的:验证 flush() 可立即执行并返回结果,清空定时器。
 */
let count4 = 0
const fn4 = () => {
  count4++
  return 'result'
}
const debouncedFn4 = debounce(fn4, 200)

debouncedFn4()
const res = debouncedFn4.flush()
console.log(res) // 'result'
// 立即执行函数,count = 1
// res = 'result'
// 定时器清空

/**
 * ================== isPending () 状态判断 ==================
 * 目的:验证函数执行前后状态正确。
 */
const debouncedFn5 = debounce(() => {}, 200)

debouncedFn5()
const pending1 = debouncedFn5.isPending()
console.log(pending1) // true

setTimeout(() => {
  const pending2 = debouncedFn5.isPending()
  console.log(pending2) // false
}, 200)
// 触发后 → pending1 = true
// 延迟结束后 → pending2 = false

/**
 * ================== this 绑定测试 ==================
 * 目的:验证防抖函数不丢失 this 指向。
 */
const obj = {
  name: 'test',
  getName() {
    return this.name
  }
}
const debouncedFn6 = debounce(obj.getName.bind(obj), 200)
debouncedFn6() // 'test'
// this 正确指向 obj
// 执行返回 test

/**
 * ================== 参数传递测试 ==================
 * 目的:验证函数参数正常传递。
 */
let result: any
const fn = (a: number, b: string) => {
  result = [a, b]
}
const debouncedFn7 = debounce(fn, 200)

debouncedFn7(1, 'test')
// 200ms 后 result = [1, 'test']

/**
 * ================== 返回值测试 ==================
 * 目的:验证函数返回值可被接收(尤其是 immediate + flush)。
 */
const fn8 = () => 'success'
const debouncedFn8 = debounce(fn8, 200, true)

const res1 = debouncedFn8()
console.log(res1) // 'success'
const res2 = debouncedFn8.flush()
console.log(res2) // 'success'

/**
 * ================== 连续高频触发测试 ==================
 * 目的:验证极端场景下防抖依然稳定。
 */
let count9 = 0
const debouncedFn9 = debounce(() => count9++, 100)

// 10ms 内疯狂触发 100 次
for (let i = 0; i < 100; i++) {
  setTimeout(() => debouncedFn9(), i * 10)
}
// 最终只执行 1 次 count = 1

/**
 * ================== 边界异常场景测试 ==================
 * 目的:验证异常输入不崩溃。
 */
// 测试1:delay 为 0
debounce(() => {}, 0)()

// 测试2:delay 为负数
debounce(() => {}, -100)()

// 测试3:fn 为 undefined/非函数
// @ts-ignore
debounce(undefined)()
// @ts-ignore
debounce(123)()

基于 MIT 许可发布