浅谈 防抖和节流

防抖和节流:是优化高频率执行代码的手段。

目的:节约浏览器、服务器的性能。

主要方式:减少函数执行的次数。

函数防抖(debounce)

函数防抖:事件被触发,等待n秒后再执行回调,如果在这n秒内又被触发,则重新计数。

防抖的目的:目的是为了让一定时间段的连续的函数调用,只让其执行一次。

我们来举一个上电梯的例子: 电梯总是在进出人(监听事件)之后的5秒关门(执行方法), 如果5秒钟之内又有人进出, 则重新开始计时, 直到最后一个进出电梯的事件发生5秒钟之后执行关门。

函数节流(throttle)

函数节流:规定在一个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某某被触发多次,则只有一次能生效。

节流的目的:是让一个函数不要执行太频繁,减少一些过快的调用来节流。

常用到的场景

  • 返回顶部问题
  • 搜索框input事件,例如要支持输入实时搜索可以使用节流方案(间隔一段时间就必须查询相关内容),或者实现输入间隔大于某个值(如500ms),就当做用户输入完成,然后开始搜索,具体使用哪种方案要看业务需求。
  • 页面resize事件,常见于需要做页面适配的时候。需要根据最终呈现的页面情况进行dom渲染(这种情形一般是使用防抖,因为只需要判断最后一次的变化情况)
/* debounce */
function debounce(fn, wait) {
    var timer = null;
    return function () {
        var context = this;
        var args = arguments;

        // 如果在n秒内还有定时未执行,则删除之前的定时任务
        if (timer) {
            clearTimeout(timer);
            timer = null;
        }

        // 重新设定定时任务
        timer = setTimeout(function () {
            fn.apply(context, args);
        }, wait);
    }
}

var fn = function () {
    console.log('debounce function doing...');
}

// 第一次在1500ms后触发,之后每1000ms触发一次
setInterval(debounce(fn, 500), 1000);

// 不会触发一条
setInterval(debounce(fn, 2000), 1000);


/* throttle */
function throttle(fn, gapTime) {
    var _lastTime = null;
    var timer = null;

    return function () {
        var _nowTime = new Date().getTime();
        var context = this;
        var args = arguments;

        if (!_lastTime) {
            _lastTime = new Date().getTime();
            fn.apply(context, args);
        } else if (_nowTime - _lastTime < gapTime) {
            if (timer) {
                clearTimeout(timer);
                timer = null;
            }
            timer = setTimeout(function () {
                // 这个定时函数一直都没有执行,因为当周期时间(如10ms)小于定时时间(如1000ms)时
                // 总是在不停的clearTimeout和setTimeout,所以就永远进入不到这个函数体
                // 除非对最外面的周期函数使用clearTimeout,那么才会执行一次这个函数体
                _lastTime = new Date().getTime();
                fn.apply(context, args)
            }, gapTime);
        } else {
            _lastTime = new Date().getTime();
            fn.apply(context, args);
        }
    }
}

var fn = function () {
    console.log('throttle function doing...');
}

test = setInterval(throttle(fn, 1000), 10)

clearTimeout(test);
发布了87 篇原创文章 · 获赞 3 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_38188762/article/details/105165682