跳至主要內容

防抖函数

haneball大约 1 分钟JavaScriptTypeScript性能优化

概述

  • 当事件触发时,函数 fn 不会立即执行,而是等待一段时间
  • 若等待时间内没有再次触发事件,则执行函数 fn
  • 当事件被频繁触发时,防抖函数 debounce 表现为延迟执行

实现

type fnType<T> = (...args: T[]) => any

/**
 * 防抖
 * @param fn 需要防抖的函数
 * @param delay 延迟时间, 单位毫秒 ms, 默认 200
 * @param immediate 是否立即执行, 默认不立即执行
 * @returns 防抖化的函数
 */
function debounce<T = any>(fn: fnType<T>, delay: number = 200, immediate: boolean = false) {
    let timer: any = null
    let isInvoke = false    // 是否已执行

    const _debounce = function(...args: T[]) {
        return new Promise<T>((resolve, reject) => {
            // 清除计时器
            if (timer) clearTimeout(timer)
    
            if (!isInvoke && immediate) {    // 立即执行 1 次
                try {
                    const result = fn.apply(this, args)
                    // 立即执行完成
                    isInvoke = true
                    resolve(result)
                } catch(err: any) {
                    reject(err)
                }
            } else {
                timer = setTimeout(() => {
                    try {
                        const result = fn.apply(this.args)
                        // 执行完成, 初始化所有变量
                        timer = null
                        isInvoke = false
                        resolve(result)
                    } catch (err: any) {
                        reject(err)
                    }
                }, delay)
            }
        })
    }

    // 取消执行
    _debounce.cancel = function() {
        clearTimeout(timer)
        timer = null
    }

    return _debounce
}