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)()