防抖和节流的实现、区别与应用场景

应用: 在我们开发过程中,会有一些用户操作,如滚动事件,输入事件等导致一直重复调用某函数,频率无限,使浏览器负担过重,导致页面卡顿。这时候就会用到防抖和节流来控制调用频率,减少浏览器负担。

区别:防抖:设置一个时间段A来做延时,在事件触发后A时间段内没有再次触发事件,那么函数会在A时间段过后自动执行一次;如果在还没到达A时间段,再次触发事件,那么会根据最后一次触发来重新计算A时间段,延时执行;如下图:

节流:设置一个时间段B,在事件触发后,B时间后再次执行,不管用户触发多少遍事件,函数只会每隔B段时间执行一次;

综上所述:防抖就是将无限次数变为最后一次执行,节流是将无限次数变为每隔一段时间执行;


实现:防抖(debounce):防抖分为非立即执行与立即执行,非立即执行为触发后过一段时间才执行函数;立即执行为触发后马上执行函数,然后等待规定时间过后,再次触发有效,再次立即执行;

非立即执行:

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <title>加入防抖</title>
 <style type="text/css">
#box{width:500px;
height: 500px;
background: red;}
 </style>
</head>

<body>
 <div>
加入防抖后的输入:非立即执行
 <input type="text" name="debounce" id="debounce">
 <div id='box'>
在此移动
 </div>
 </div>
 <script type="text/javascript">
 // 防抖
 //非立即执行
 var i=0;
function debounce(fn, wait) { 
    console.log("执行")
    var timeout ; 
    return function(){
      if(timeout!== null) {
          clearTimeout(timeout)
        }
      timeout = setTimeout(fn,wait);    
    }
}
// 处理函数
function handle() {    
  i++;
   console.log(i+"次执行")
}
//触发事件 展示两种例子
//鼠标移动事件
 var box=document.getElementById('box');
 box.onmousemove=debounce(handle, 1000);
//键盘输入事件
var inp=document.getElementById('debounce');
inp.onkeyup=debounce(handle, 1000);
 </script>
</body>

</html>

立即执行:

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <title>加入防抖</title>
 <style type="text/css">
#box{width:500px;
height: 500px;
background: red;}
 </style>
</head>

<body>
 <div>
加入防抖后的输入:立即执行
 <input type="text" name="debounce" id="debounce">
 <div id='box'>
在此移动
 </div>
 </div>
 <script type="text/javascript">
 // 防抖
 //立即执行
 var i=0;
function debounce(fn, wait) { 
    var timeout ; 
    return function(){
      if(timeout!== null) {
          clearTimeout(timeout)
        }
      var flag=!timeout;
      timeout = setTimeout(function(){
        timeout=null;
      },wait);   
      if(flag){
        handle()
      } 
    }
}
// 处理函数
function handle() {    
  i++;
   console.log(i+"次执行")
}
//触发事件  展示两种例子
//鼠标移动事件
var box=document.getElementById('box');
 box.onmousemove=debounce(handle, 1000);
//键盘输入事件
var inp=document.getElementById('debounce');
inp.onkeyup=debounce(handle, 1000);
 </script>
</body>

</html>

节流(throttle):实现函数节流也有两种办法:时间戳和定时器; 时间戳方法:

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <title>加入防抖</title>
 <style type="text/css">
   #box{
     width:500px;
     height: 500px;
     background: red;
   }
 </style>
</head>
<body>
 <div>
    加入节流后的输入:时间戳
    <input type="text" name="debounce" id="inp">
    <div id='box'>
     在此移动
    </div>
 </div>
 <script type="text/javascript">
//节流
 var i=0;
var throttle = function(fn, way) {
    var prev = Date.now();
    return function() {
        var now = Date.now();
        if (now - prev >= way) {
            handle();
            prev = Date.now();
        }
    }
}
function handle() {
  i++;
    console.log(i+"次数");
}
//触发事件 展示两种例子
//鼠标移动事件
var box=document.getElementById('box');
 box.onmousemove=throttle(handle, 3000);
//键盘输入事件
var inp=document.getElementById('inp');
inp.onkeyup=throttle(handle, 3000);
</script>
</body>

</html>

定时器:

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <title>加入防抖</title>
 <style type="text/css">
#box{width:500px;
height: 500px;
background: red;}
 </style>
</head>

<body>
 <div>
加入节流后的输入:定时器
 <input type="text" name="debounce" id="inp">
 <div id='box'>
在此移动
 </div>
 </div>
 <script type="text/javascript">
 // 节流
 var i=0;
var throttle = function(fn, way) {
   var timer = null;
    return function() {
        if (!timer) {
            timer = setTimeout(function(){
              handle()
              timer=null;
            }, way);
        }
    }
}
function handle() {
  i++;
    console.log(i+"次数");
}
//触发事件 展示两种例子
//鼠标移动事件
var box=document.getElementById('box');
 box.onmousemove=throttle(handle, 2000);
//键盘输入事件
var inp=document.getElementById('inp');
inp.onkeyup=throttle(handle, 2000);
</script>
</body>
</html>

以上两种方式,都各有弊端,时间戳在最后一次触发后不执行函数,而定时器是第一次触发的时候没有立即执行函数,这两种方式无法完美的满足需求,所以我们优化了一下节流方式,如下:

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <title>加入防抖</title>
 <style type="text/css">
#box{width:500px;
height: 500px;
background: red;}
 </style>
</head>

<body>
 <div>
加入节流后的输入:定时器
 <input type="text" name="debounce" id="inp">
 <div id='box'>
在此移动
 </div>
 </div>
 <script type="text/javascript">
 // 节流
var i=0;
var throttle = function(fn, way) {
    var timer = null;
    var startTime = Date.now();
    return function() {
      var nowTime = Date.now();
      var remaining = way - (nowTime - startTime);  //剩余时间
      clearTimeout(timer);
      if (remaining <= 0) {      // 第一次触发立即执行
           handle()
          startTime = Date.now();
      } else {
        timer = setTimeout(handle, remaining);   //取消当前计数器并计算新的remaining
      }
    }
}
function handle() {
  i++;
    console.log(i+"次数");
}
//触发事件 展示两种例子
//鼠标移动事件
var box=document.getElementById('box');
 box.onmousemove=throttle(handle, 3000);
//键盘输入事件
var inp=document.getElementById('inp');
inp.onkeyup=throttle(handle, 3000);
 </script>
</body>

</html>

时间戳+定时器版有bug,请各位同猿指正错误,感谢!

原文链接:segmentfault.com

上一篇:突破:Ajax请求
下一篇:阿里云部署 5.域名、DNS、nginx

相关推荐

  • 防抖(debounce)和节流(throttle)的学习总结

    防抖(debounce) 用户与网页进行交互时,经常出现根据页面的状态、数据向服务器请求、发送数据的场景,比如:根据用户的输入数据进行实时校验,下拉请求数据等等,如果用户操作过于频繁,页面状态、数...

    1 年前
  • 防抖(debounce)和节流(throttle)---解决事件频繁触发造成页面卡死

    连续触发(触发频率很高)的时间,不进行优化,会出现页面卡顿现象。 常见的需要优化的事件: 鼠标事件: mousemove(拖拽) mouseover(划过) ...

    1 年前
  • 防抖和节流的实现

    防抖(debounce) 防抖的作用是将多个连续的调用合并为一次调用。作用见参考资料1。 1. 两次调用的间隔小于,则视为连续的调用。 2. 如果距离上次调用已经过去了的时间,则说明该轮连续...

    2 年前
  • 防抖和节流(较全&可体验)

    (https://img.javascriptcn.com/3c2d27a3a2e77b5c149efb2cd4a1b942) 防抖(debounce) 概念 事件被触发经过单位时间(del...

    7 个月前
  • 防抖动处理和节流 小技巧

    1. 简单的防抖动处理,一秒内点击一次 2. 向服务器请求数据 点击按钮向后台请求数据 优化点: 另外一些防抖动的小技巧,请参考: http://blog.csdn.net/crys...

    2 年前
  • 防抖与节流(源码学习)

    最近自己撸了一个轮播图,在点击切换的时候,为了寻求更好的用户体验,引入了节流,在此记录对源码的学习过程 源码来源:underscore(https://github.com/jashkenas/und...

    2 年前
  • 防抖、节流

    防抖(debounce) n秒内执行多次同一函数只有最后一次有效。 实现方式:使用计时器,在 n 秒内再执行该函数,如果 n 秒内再次调用该函数,则重置计时器。 节流(throttle) n秒内执行多...

    3 天前
  • 重拾JS——防抖与节流

    防抖 与 节流 是前端在优化性能问题上,经常使用的两种技术手段。比如 input,scroll,resize,mousemove 等事件,如果不加以控制,频繁的触发,无疑将会带来额外的性能开销,极端情...

    1 个月前
  • 谈谈服务端渲染的理解以及使⽤场景

    Screen Shot 20200518 at 11.54.37 PM.png(/public/upload/540f63c5c7ed6363a1f94b430a14e9b6) 优点: 1.有...

    17 天前
  • 说说JavaScript中函数的防抖 (Debounce) 与节流 (Throttle)

    为何要防抖和节流 有时候会在项目开发中频繁地触发一些事件,如 、 、 、 等,或者诸如输入框的实时搜索功能,我们知道如果事件处理函数无限制调用,会大大加重浏览器的工作量,有可能导致页面卡顿影响体验...

    1 年前

官方社区

扫码加入 JavaScript 社区