一步步优化实现完美的函数防抖

1,540 阅读2分钟

什么是函数防抖

一个原本延迟N秒执行的函数在执行前被反复触发时,重新计算延时。

最简单的实现方法

App.vue

<template>
    <div>
        <button @click="debounceTest('函数防抖')">模拟防抖事件的触发</button>
    </div>
</template>

<script>
let timerId = null;
export default {
    methods: {
        debounceTest(message) {
            console.log("按钮被单击了。。。", timerId);
            if (timerId) {
                clearTimeout(timerId);
                timerId = null;
            }
            timerId = setTimeout(() => {
                console.log("执行防抖函数代码:", message);
            }, 1000);

        },
    },
};
</script>

虽然可以试下防抖,但是没有复用性,如果另一个函数也需要防抖,还需要重新写一份。

封装一个工具函数

App.vue

 <template>
    <div>
        <button @click="debounceTest('函数防抖')">模拟防抖事件的触发</button>
    </div>
</template>

<script>
import  util from './utils'
console.log(util)
export default {
    methods: {
        debounce: util.debounce,
        debounceTest(message) {
            this.debounce(()=>{
                console.log("执行防抖函数代码:", message);
            }, 2000)()
        },
    },
};
</script>

util.js

let  timerId = null;

function debounce(fn, timerForWait=1000) {
    console.log('发起了调用请求');
    return function() {
        if (timerId) {
            clearTimeout(timerId);
        }
        timerId = setTimeout(() => {
            fn()
        }, timerForWait);
    }
}

export default {debounce};

上面的写法还是有点缺陷,

  1. 计时器作为模块内部变量,所有函数公用一个计时器,还是无法实现公用。
  2. 函数作为参数的传递方式不是很优雅

最终版

util.js

function debounce(fn, timerForWait=1000) {
    console.log('发起了调用请求')
    return function() {
        if (fn.timerId) {
            clearTimeout(fn.timerId);
        }
        fn.timerId = setTimeout(() => {
            fn(...arguments)
        }, timerForWait);
    }
}

export default {debounce};

App.vue

<template>
    <div>
        <button @click="debounce(debounceTest, 2000)('函数防抖',',2秒后执行')">模拟防抖事件的触发</button>
        <button @click="debounce(debounceTest2, 1000)('函数防抖2',',2秒后执行')">模拟防抖事件的触发</button>
    </div>
</template>

<script>
import  util from './utils'
export default {
    methods: {
        debounce: util.debounce,
        debounceTest(message, time) {
            console.log("执行防抖函数代码:", message+time);
        },
        debounceTest2(message, time) {
            console.log("执行防抖函数2代码:", message+time);
        },
    },
};
</script>