javascript中的防抖与节流

防抖与节流是在实际开发中使用较多的功能,虽然平时我们可以使用lodash提供的功能方法,但是为了知其所以然,我们还是需要了解下它的实现原理。

1. 防抖 (debounce)

作用:防抖顾名思义就是防止抖动,如比一个常见的使用场景,当我们填完用户名密码后需要点击登录按钮,如果我的手抖动了一下,按了两次登录按钮,是不是就会请求两次登录接口呢,所以为了节约网络资源,防止不必要的网络开销,防抖是必不可少的。(我们可以通俗的记忆: 防抖是为了防止手抖,触发多次事件,它的目的是让事件在指定时间只触发一次)。

分类:即时触发和延时触发

即时触发:第一次点击时候即执行事件,后面每次点击都会刷新下次再生效的时间。

延时触发:每次点击都会刷新下次生效的时间,当到时间后就会触发一次事件。

通过文字说可能理解有点困难,下面我们还是上代码。

即时触发

function debounce(fn, wait) {
    let timer = null;
   let context = null;
return function () {
context = this;
!timer && fn(context, ...arguments); if (timer) { clearTimeout(timer); timer = null; } timer = setTimeout(() => { clearTimeout(timer); timer = null; }, wait); } }

延时触发

function delayDebounce(fn, wait) {
    let timer = null;
   let context = null;
return function() {
     context = this;
if(timer) { clearTimeout(timer); timer = null; } timer = setTimeout(() => { fn(context, ...arguments); clearTimeout(timer); timer = null; }, wait); } }

下面我们将这两个方法合并下,添加参数进行区别。

function debounce(fn, wait, immediate = true) {
    let timer = null;
    let context = null;

    return function () {
        context = this;

        if (immediate) {
            !timer && fn.call(context, ...arguments);
        }

        if (timer) {
            clearTimeout(timer);
            timer = null;
        }

        timer = setTimeout(() => {
            !immediate && fn(context, ...arguments)

            clearTimeout(timer);
            timer = null;
        }, wait);
    }
}

2. 节流

作用:顾名思义,节流就是节约流动。我们经常见到的一个使用场景就是春节期间各大公司开发的抢红包功能,需要我们不停的点击按钮,为了减少网络请求,我们就可以减少请求次数,让网络请求减少,同样达到减少网络开销的问题。(对比防抖,我们可以这样记忆:节流是减少网络请求次数,但是实际还是触发多次)。

节流也分为即时执行版本和延时执行版本。

即时执行

function throttling(fn, wait) {
    let timer = null;
    let context = this;

    return function () {
        !timer && fn.call(context, ...arguments);

        if (!timer) {
            timer = setTimeout(() => {
                clearTimeout(timer);
                timer = null;
            }, wait);
        }
    }
}

延时执行

function throttling(fn, wait, immediate = true) {
    let timer = null;
    let context = this;

    return function () {
        if (immediate) {
            !timer && fn.call(context, ...arguments);
        }

        if (!timer) {
            timer = setTimeout(() => {
                !immediate && fn.call(context, ...arguments);
                clearTimeout(timer);
                timer = null;
            }, wait);
        }
    }
}

浅陋见识,不足之处,请大神指正。

原文地址:https://www.cnblogs.com/heshuaiblog/p/14032788.html