防抖和節流的實現、區別與應用場景

應用
在咱們開發過程當中,會有一些用戶操做,如滾動事件,輸入事件等致使一直重複調用某函數,頻率無限,使瀏覽器負擔太重,致使頁面卡頓。這時候就會用到防抖和節流來控制調用頻率,減小瀏覽器負擔。javascript

區別:
防抖:設置一個時間段A來作延時,在事件觸發後A時間段內沒有再次觸發事件,那麼函數會在A時間段事後自動執行一次;若是在還沒到達A時間段,再次觸發事件,那麼會根據最後一次觸發來從新計算A時間段,延時執行;以下圖:
防抖.jpegcss

節流:設置一個時間段B,在事件觸發後,B時間後再次執行,無論用戶觸發多少遍事件,函數只會每隔B段時間執行一次;
節流.jpeghtml

綜上所述:防抖就是將無限次數變爲最後一次執行,節流是將無限次數變爲每隔一段時間執行;java


實現:
防抖(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):實現函數節流也有兩種辦法:時間戳和定時器;
時間戳方法:spa

<!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>

定時器:3d

<!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>

以上兩種方式,都各有弊端,時間戳在最後一次觸發後不執行函數,而定時器是第一次觸發的時候沒有當即執行函數,這兩種方式沒法完美的知足需求,因此咱們優化了一下節流方式,以下:code

<!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) {
  console.log(11)
    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(function(){
           i++;
        console.log(i+"次數"); 
        startTime = Date.now();
        }, 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>

時間戳+定時器版若有優化建議,歡迎提出!跪謝!

相關文章
相關標籤/搜索