GVKun编程网logo

前端函数防抖(debounce)和函数节流(throttle)(函数防抖和节流js实现)

15

如果您对前端函数防抖(debounce)和函数节流(throttle)和函数防抖和节流js实现感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解前端函数防抖(debounce)和函数节流(thro

如果您对前端函数防抖(debounce)和函数节流(throttle)函数防抖和节流js实现感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解前端函数防抖(debounce)和函数节流(throttle)的各种细节,并对函数防抖和节流js实现进行深入的分析,此外还有关于debounce(防抖)和throttle(节流)、DebounceVsThrottle(防抖和节流)、JavaScript 函数节流 throttle 和防抖 debounce、javascript函数的节流throttle与防抖debounce详解的实用技巧。

本文目录一览:

前端函数防抖(debounce)和函数节流(throttle)(函数防抖和节流js实现)

前端函数防抖(debounce)和函数节流(throttle)(函数防抖和节流js实现)

防抖&节流

在前端开发中一部分的用户行为会频繁的出发事件执行,对DOM操作、资源加载等耗费性能的处理,很可能导致界面卡顿,甚至浏览器的崩溃。函数防抖(debounce)和函数节流(throttle)就是为了解决类似的需求应运而生的。

 

  • 防抖

函数防抖就是在函数需要频繁触发情况时,只有足够空闲的时间,才执行一次。好像公交车司机会等全部人上车后才出站一样。

 

应用场景:实时搜索(keyup)、拖拽(mousemove)

 

var input = document.getElementsByTagName(''input'')[0];
var timer = null;
function ajax() {
    console.log(this.value);    
}
input.oninput = function () {
  var _self = this,
_arg = arguments;
  clearTimeout(timer);
  timer = setTimeout(function () {
    ajax.apply(_self, _arg);
  }, 1000);
}

 

封装防抖函数

function debounce(handler, delay) {
    var timer = null;
    return function () {
        var _self = this,
             _arg = arguments;
        clearTimeout(timer);
        timer = setTimeout(function () {
            handler.apply(_self, _arg);
        }, delay);
    }  
}

 

  • 节流

函数节流就是预定一个函数只有在大于等于执行周期时才执行,周期内调用不执行。好像水滴攒到一定重量才会落下。

 

应用场景:窗口调整(resize)、页面滚动(scroll)、抢购疯狂点击(mousedowm)

 

function throttle(handler, wait) {
    var lastTime = 0;
    return function () {
        var nowTime = new Date().getTime();
        if (nowTime - lastTime > wait) {
            handler.apply(this, arguments);
            lastTime = nowTime;
        }
    }
}

 

debounce(防抖)和throttle(节流)

debounce(防抖)和throttle(节流)

防抖和节流

窗口的resizescroll,输入框内容校验等操作时,如果这些操作处理函数较为复杂或页面频繁重渲染等操作时,如果事件触发的频率无限制,会加重浏览器的负担,导致用户体验非常糟糕。此时我们可以采用debounce(防抖)和throttle(节流)的方式来减少触发的频率,同时又不影响实际效果。

debounce 防抖

debounce(防抖),简单来说就是防止抖动。

debounce 防抖

从上图中我们可以看到,当持续触发事件时,debounce会合并事件且不会去触发事件,当一定时间内没有触发再这个事件时,才真正去触发事件~ 一起来实现个简单的debounce:

function debounce(fn, delay) {
  var ctx;
  var args;
  var timer = null;

  var later = function () {
    fn.apply(ctx, args);
    // 当事件真正执行后,清空定时器
    timer = null;
  };

  return function () {
    ctx = this;
    args = arguments;
    // 当持续触发事件时,若发现事件触发的定时器已设置时,则清除之前的定时器
    if (timer) {
      clearTimeout(timer);
      timer = null;
    }

    // 重新设置事件触发的定时器
    timer = setTimeout(later, delay);
  };
}

效果图:

sample debounce

throttle 节流

throttle(节流),当持续触发事件时,保证隔间时间触发一次事件。

throttle 节流

上图中绿色块表示触发一次事件,持续触发事件时,throttle会合并一定时间内的事件,并在该时间结束时真正去触发一次事件~ 一起来看看throttle的简单实现:

function throttle(fn, delay) {
  var ctx;
  var args;
  // 记录上次触发事件
  var previous = Date.now();

  var later = function () {
    fn.apply(ctx, args);
  };

  return function () {
    ctx = this;
    args = arguments;
    var now = Date.now();
    // 本次事件触发与上一次的时间比较
    var diff = now - previous - delay;

    // 如果隔间时间超过设定时间,即再次设置事件触发的定时器
    if (diff >= 0) {
      // 更新最近事件触发的时间
      previous = now;
      setTimeout(later, delay);
    }
  };
}

效果图:

sample throttle

总结

根据实际业务场景,合理的利用debounce(防抖)和throttle(节流)可以优化性能和提高用户体验。两者间的核心区别就在于持续触发事件时,前者合并事件并在最后时间去触发事件,而后者则是隔间时间触发一次~

关键知识点

setTimeout 定时器

w3school

Closure 闭包

ruanyifeng

资源

在线测试

源代码

DebounceVsThrottle(防抖和节流)

DebounceVsThrottle(防抖和节流)

本人原文

不从概念触发,先从应用讲起。如果要你设计一个输入搜索组件,你会怎么做。可能你觉得很简单,响应输入框的 keydown 和 change 事件,然后向服务器发起请求就可以了。这样的处理方案思路上是没毛病的,不过会存在两个问题,分别影响客户端和服务器。

  1. 过于频繁的响应事件,会降低用户体验。
  2. 过于频繁的请求服务器,增加服务器压力。

我们先思考一下用户增加、删除一个字符就发起请求的合理性。一般而言,搜索单个字符对于用户来说是没有意义的,用户往往是需要搜索一个单词或者短语。那么使用以上的设计,在用户输入他想要搜索的文字之前的所有搜索,都是浪费的请求。同时,过于频繁的处理事件,当事件响应变多了之后,页面会出现卡顿也是理所当然的事。另外,对于服务器而言,搜索一般来说本身就是比较复杂、耗时的服务,过多的请求不可避免地增加服务器的并发量更是给服务器增加压力。

从以上的简单分析可以知道,我们并不需要对用户的输入进行立马响应,可以等待用户输入停止之后再进行实际的逻辑处理,这样的设计也是更符合用户体验的。

这样的想法就是所谓的防抖,而另一个相似的做法是节流。他们的区别是,防抖是在最后一次事件触发后等待一定的时间再做逻辑处理,如果在这个等待时间结束之前有新的事件发生,那么这个事件就是最后一次事件,逻辑处理的时机也要相应往后延;而节流是每隔一定时间就做一次逻辑处理。他们的共同点都是降低逻辑处理的频率。

简单的防抖代码如下

function debounce(func, timespan) {
  let timer;

  return function () {
    const context = this;
    const args = arguments;

    clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(context, args);
    }, timespan);
  };
}

简单的节流代码如下

function throttle(func, timespan) {
  let running = false;
  let context;
  let args;

  return function () {
    context = this;
    args = arguments;

    if (!running) {
      running = true;
      setTimeout(() => {
        func.apply(context, args);
        running = false;
      }, timespan);
    }
  };
}

一张图来对比一下他们在时序上的区别(上边是 debounce,下边是 throttle,每个框等时长)

JavaScript 函数节流 throttle 和防抖 debounce

JavaScript 函数节流 throttle 和防抖 debounce

今天和别人聊到JavaScript函数的节流和防抖,发现自己对这两个的区别很是模糊,遂小小实践一下,在此记录,希望对需要的人有所帮助。

节流 - 频繁操作,间隔一定时间去做一件事

举例说明:假定时间间隔为 500ms,频繁不停的操作 2s,且每两次执行时间小于等于时间间隔 500ms,那么就会执行 4 次,也就是每隔 时间间隔 500ms 执行一次。

防抖 - 频繁操作,一定时间间隔内只执行最后一次操作

举例说明:假定时间间隔是 500ms,频繁不停的操作 5s,且每两次执行时间小于等于时间间隔 500ms,那么最后只执行了 1 次,也就是每一次执行时都结束了上一次的执行。

代码示例

    //节流方法 1
    function throttle1(method, duration){
        var prevTime = new Date();
        return function () {
            var context = this,
                currentTime = new Date(),
                resTime = currentTime - prevTime;
            //打印出本次调用方法和上次执行方法的时间差
            console.log("时间差"+resTime);
            //当本次调用距离上次执行方法的时间差大于等于要求时间间隔时,执行一次方法
            if(resTime >= duration){
                method.apply(context);
                //记录执行方法的时间
                prevTime = currentTime;
            }
        }
    }
    //节流方法 2
    function throttle2(method, duration){
        //当前时间间隔内是否有方法在执行(或者说方法的调用是否在进行)
        var runningFlag = false;
        return function (e) {
            // 判断当前是否有方法在执行,有,则什么都不做
            if (runningFlag) {
                return false;
            }
            //开始执行
            runningFlag = true;
            setTimeout(function(){
                method(e);
                //执行完毕,声明当前没有正在执行的方法,方便下一个时间间隔内的调用
                runningFlag = false;
            }, duration)
        }
    }
    //防抖
    function debounce(method, duration){
        var timer = null;
        return function(){
            var context = this,
                args = arguments;
            //在本次调用之前的一个间隔时间内,有方法在执行,则终止该方法的执行
            if(timer){
                clearTimeout(timer);
            }
            //开始执行本次调用
            timer = setTimeout(function(){
                method.apply(context, args);
            },duration);
        }
    }
    //模拟三个执行方法
    function jieliu1(){
        console.log("节流 1");
    }
    function jieliu2(){
        console.log("节流 2");
    }
    function fangdou(){
        console.log("防抖");
    }
    //持续执行时间
    var totalTime = 2000;

    var jieliuFn1 = throttle1(jieliu1,500);
    var jieliuFn2 = throttle2(jieliu2,500);
    var fangdouFn = debounce(fangdou,500);

    (function(duration){
        setInterval(function(){
            if( totalTime > 0 ){
                jieliuFn1();
                jieliuFn2();
                fangdouFn();
                totalTime -= duration;
            }
        },duration);
    })(100);

运行结果

时间差 100
时间差 201
时间差 303
时间差 401
时间差 504
节流 1
时间差 98
节流 2
时间差 199
时间差 300
时间差 396
时间差 496
时间差 597
节流 1
时间差 100
节流 2
时间差 203
时间差 299
时间差 402
时间差 500
节流 1
时间差 103
时间差 204
节流 2
时间差 303
时间差 400
节流 2
防抖

结论

由以上运行结果可以看出,节流1 出现了 3 次,节流2 出现了 4 次,防抖出现了 1 次。防抖实现顺利,但是两个节流方法的执行结果存在差异。
观察时间差可以看出,每次节流1 执行时,时间差并不会都是 500 整,也就是说,一共调用 2 秒时,节流1 并不能做到每隔 500 毫秒执行一次而共执行 4 次,第四次执行往往因为前面的 3 次执行的时间误差,而导致到达时间 2 秒时,最后一次的时间差无法达到 时间间隔 500ms 以上,以至于只能执行 3 次。

结论:当在一个大范围的时间内,比如两小时内,每几分钟执行一次,超过2小时则不再实行,推荐使用第一种节流方式,;如果仅仅要求间隔一定时间执行一次,推荐使用第二种节流方法;防止频繁操作,比如表单多次提交,推荐使用防抖。

如有问题,欢迎指正,谢谢!

javascript函数的节流throttle与防抖debounce详解

javascript函数的节流throttle与防抖debounce详解

本文主要介绍了javascript函数的节流[throttle]与防抖[debounce ],详细的介绍了节流与防抖的原理和示例,具有一定的参考价值,有兴趣的可以了解一下,希望能帮助到大家。

防抖和节流

窗口的resize、scroll,输入框内容校验等操作时,如果这些操作处理函数较为复杂或页面频繁重渲染等操作时,如果事件触发的频率无限制,会加重浏览器的负担,导致用户体验非常糟糕。此时我们可以采用debounce(防抖)和throttle(节流)的方式来减少触发的频率,同时又不影响实际效果。

这两个东西都是为了项目优化而出现的,官方是没有具体定义的,他们的出现主要是为了解决一些短时间内连续执行的事件带来性能上的不佳和内存的消耗巨大等问题;

像这类事件一般像 scroll keyup mousemove resize等等,短时间内不断的触发,在性能上消耗是非常大的,尤其是一些改变DOM结构的操作;

立即学习“Java免费学习笔记(深入)”;

节流[throttle]与防抖[debounce]非常相似,都是让上述这类事件在规定的事件从不断的去触发更改成为规定的时间内触发多少次;

节流[throttle]

节流通俗来解释就比如我们水龙头放水,阀门一打开,水哗哗的往下流,这个秉着勤俭节约的优良传统美德,我们要把水龙头关小点,最好是如我们心意按照一定规律在某个时间间隔内一滴一滴的往下滴,这,,,好吧这就是我们节流的概念;

换成函数来说,使用setTimeout方法,给定两个时间,后面的时间减去前面的时间,到达我们给定的时间就去触发一次这个事件,这么说太笼统的,我们看下面的函数,这里我们以【scroll】为例;


/** 样式我就顺便写了 **/
<style>
 *{padding:0;margin:0;}
 .scroll-box{
  width : 100%;
  height : 500px;
  background:blue;
  overflow : auto;
 } 
 .scroll-item{
  height:1000px;
  width:100%;
 }
</style>
登录后复制

------------------------


/** 先给定DOM结构;**/
<p>
 <p></p>
</p>
登录后复制

------------------------


/**主要看js,为了简单我用JQ去写了**/
<script>
 $(document).ready(function(){
  var scrollBox = $(&#39;.scroll-box&#39;);
  //调用throttle函数,传入相应的方法和规定的时间;
  var thro = throttle(throFun,300);
  //触发事件;
  scrollBox.on(&#39;scroll&#39; , function(){
   //调用执行函数;
   thro();
  })

  // 封装函数; 
  function throttle(method,time){
   var timer = null;
   var startTime = new Date();
   return function(){
    var context = this;
    var endTime = new Date();
    var resTime = endTime - startTime;
    //判断大于等于我们给的时间采取执行函数;
    if(resTime >= time){
     method.call(context);
     //执行完函数之后重置初始时间,等于最后一次触发的时间
     startTime = endTime;
    }
   }
  }
  function throFun(){
   console.log(&#39;success&#39;);
  }
 })
</script>
登录后复制

通过以上的函数,我们就可以做到节流的效果,在规定的每300毫秒触发一次,当然时间可以自定义,根据需求来;

防抖[debounce ]

写代码之前,我们先清楚一下防抖的概念,不知道大家有没有做过电脑端两边悬浮广告窗口的这么一个东西,当我们拖动滚动条的时候,两边的广告窗口会因为滚动条的拖动,而不断的尝试着去居于中间,然后你就会看到这两个窗口,不停的抖啊抖;

一般这种就叫抖动了,我们要做的就是防止这种抖动,称为防抖[debounce ];

那这里防抖思想就是当我们拖动完成之后,两边的窗口位置再重新去计算,这样,就会显得很平滑,看着很舒服了,最主要的操作DOM结构的次数就大大减少了;

优化了页面性能,降低了内存消耗,不然你像IE这种比较老点版本的浏览器,说不定就直接给你蹦了

用书面一点的说法就是,在某个事件没有结束之前,函数不会执行,当结束之后,我们给定延时时间,然他在给定的延时时间之后再去执行这个函数,这就是防抖函数;

来看代码:


//将上面的throttle函数替换为debounce函数;
function debounce(method,time){
 var timer = null ;
 return function(){
  var context = this;
  //在函数执行的时候先清除timer定时器;
  clearTimeout(timer);
  timer = setTimeout(function(){
   method.call(context);
  },time);
 }
}
登录后复制

思路就是在函数执行之前,我们先清除定时器,如果函数一直执行,就会不断的去清除定时器中的方法,知道我们操作结束之后,函数才会执行;

其实书写的方式有很多,主要还是思路的问题,大家写的多了,自然就知道了;

用途

  1. 当我们做keyup像后台请求检验的时候,可以使用防抖函数,不然我们每按一次键盘就请求一次,请求太频繁,这样当我们结束按键盘的时候再去请求,请求少很多了,性能自然不用说;

  2. resize 窗口大小调整的时候,我们可以采用防抖技术也可以使用节流;

  3. mousemove 鼠标移动事件我们既可以采用防抖也可以使用节流;

  4. scroll 滚动条触发的事件,当然既可以采用防抖也可以采用节流;

  5. 连续高频发的事件都可以采用这两种方式去解决,优化页面性能;

相关推荐:

JS函数节流防抖实例详解

详解javascript函数的节流与防抖

函数节流与防抖的含义

以上就是javascript函数的节流throttle与防抖debounce详解的详细内容,更多请关注php中文网其它相关文章!

关于前端函数防抖(debounce)和函数节流(throttle)函数防抖和节流js实现的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于debounce(防抖)和throttle(节流)、DebounceVsThrottle(防抖和节流)、JavaScript 函数节流 throttle 和防抖 debounce、javascript函数的节流throttle与防抖debounce详解等相关内容,可以在本站寻找。

本文标签: