函数防抖Debounce和函数节流Throttle

函数节流 & 函数防抖

函数节流和函数防抖前端

函数节流和函数防抖两者很容易被混淆起来。下面贴英文原文,建议认真阅读:
Debouncing enforces that a function not be called again until a certain amount of time has passed without it being called. As in "execute this function only if 100 milliseconds have passed without it being called".
Throttling enforces a maximum number of times a function can be called over time. As in "execute this function at most once every 100 milliseconds".ajax

函数节流:确保函数特定的时间内至多执行一次。
函数防抖:函数在特定的时间内不被再调用后执行。浏览器

上面的概念可能仍是不够清晰,下面均以“输入框输入文字触发ajax获取数据”为例,分别以防抖和节流的思想来优化,两者的区别:性能优化

输入框输入文字以下:1111111111111111111111(停顿3s继续输入)11111111111111111
函数防抖:当用户持续输入1的过程当中,并不会发送ajax,当用户中止输入2s后,发送ajax请求,以后到第3s后,用户继续输入1的过程当中,依旧不会发送ajax,当用户中止输入2s后,又触发ajax请求。
函数节流:当用户持续输入1的过程当中(假设输入1的过程超过2s了),从你开始输入1开始计时,到第2s,发送ajax请求。函数节流与你是否中止输入无关,是一种周期性执行的策略。
一句话归纳:函数节流是从用户开始输入就开始计时,而函数节流是从用户中止输入开始计时。app

场景分析前端性能

函数节流(throttle)函数

  1. 频繁的mousemove/keydown,好比高频的鼠标移动,游戏射击类的
  2. 搜索联想(keyup)
  3. 进度条(咱们可能不须要高频的更新进度)
  4. 拖拽的dragover等
  5. 高频的点击,抽奖等
  6. 无限滚动(用户向下滚动无限滚动页面,要检查滚动位置距底部多远。若是离底部进了,发ajax请求获取更多数据插入页中)

函数防抖(debounce)性能

  1. scroll/resize事件,浏览器改变大小,有人说是throttle
  2. 文本连续输入,ajax验证/关键字搜索

注:throttle和debounce均是经过减小实际逻辑处理过程的执行来提升事件处理函数运行性能的手段,并无实质上减小事件的触发次数。优化

使用函数节流是进行前端性能优化的方法之一,例如,懒加载的实现。this

实现函数防抖和函数节流

函数防抖

function debounce(func,wait){
    var timeout;
    return function(){
        var context=this;//用来保存this的正确指向
        var args=arguments;//用来保存触发的事件类型,例如keyboard event
        clearTimeout(timeout);//每次都从新开始计时
        timeout=setTimeout(function(){
            func.apply(context,args);
        },wait);
    }
}
a.onkeyup=debounce(getValue,3000);
function getValue(){
    console.log(this.value);//使用debounce调用它时,this就变为window
}

函数节流

function throttle(func, wait) {
    var timeout, context, args, result;
    var previous = 0;
 
    var later = function() {
        previous = +new Date();
        timeout = null;
        func.apply(context, args)
    };

    var throttled = function() {
        var now = +new Date();
        //下次触发 func 剩余的时间
        var remaining = wait - (now - previous);
        context = this;
        args = arguments;
         // 若是没有剩余的时间了或者你改了系统时间
        if (remaining <= 0 || remaining > wait) {
            if (timeout) {
                clearTimeout(timeout);
                timeout = null;
            }
            previous = now;
            func.apply(context, args);
        } else if (!timeout) {
            timeout = setTimeout(later, remaining);
        }
    };
    return throttled;
}
相关文章
相关标签/搜索