1. 程式人生 > 其它 >js 的 節流 和 防抖

js 的 節流 和 防抖

目錄

節流 和 防抖 簡介

在使用者進行瀏覽器頁面的操作時,可能會發生一段時間內(如1s內),連續、頻繁點選某個操作按鈕,導致頻繁操作dom或者向後臺發出請求,可能會造成頁面卡頓或者伺服器擁堵。針對此種情況,可以使用js的 節流 和 防抖 來解決。

節流 和 防抖 這兩種方式的實現原理都是利用 setTimeOut 定時器來實現的,將使用者的操作延遲執行。

節流 和 防抖 區別

節流,採用“間隔一段時間後執行”,即 第一次觸發時,先建立一個定時器,在一定時間後再執行觸發事件,同時將定時器置為空,若在一定時間內(比如1s內)再次觸發,則會判斷定時器是否存在,如果存在,則不再建立新的定時器(後續的觸發事件不會執行);

防抖,採用“延遲執行觸發,並清除上一次的定時器”,即 第一次觸發時,先建立一個定時器,在一定時間後再執行觸發事件,若在一定時間內(比如1s內)再次觸發,則會清除之前的定時器,重新新建一個定時器;這樣會有一個缺點,就是 若在一段時間內不停地觸發事件,那麼該事件的執行會被無限期地延後。

應用場景

  1. 節流

    • 防止表單提交時重複多次觸發事件;
  2. 防抖

    • 視窗resize需計算視窗的大小時,需等使用者的拖拽事件完成後執行計算方法;

    • input 輸入框的實時查詢事件,在使用者不斷輸入的過程中不觸發查詢,等使用者輸入完停止一段時間後再觸發

程式碼實現

  • 節流
function clickFn() {
  console.log('clickFn');
}

// 節流,一段時間內只能觸發一次函式,若觸發多次,則只有一次生效(相當於執行這段時間內第一次點選的事件)
function dealFn(func, time) {
  let timer = null;
  return function() {
    let that = this;
    if(!timer) {
      timer = setTimeout(() => {
        func.call(that);
        timer = null;
      }, time)
    }
  }
}

let submitClick = dealFn(clickFn, 1000);

submitClick();
submitClick();
setTimeout(()=> {
  console.log("...");
  submitClick();
}, 1000);
  • 防抖
function clickFn() {
  console.log('clickFn');
}

// 防抖,一段時間內觸發多次函式時,每次觸發都延遲函式呼叫,並在下一次觸發時清除之前的定時器(相當於執行這段時間內最後一次點選的事件)
// 每次觸發事件時設定一個延遲呼叫方法,並且取消之前的延時呼叫方法
// 缺點:如果事件在規定的時間間隔內被不斷的觸發,則呼叫方法會被不斷的延遲
function dealFn(func, time) {
  let timer = null;
  return function() {
    let that = this;
    clearTimeout(timer);
    timer = setTimeout(() => {
      func.call(that);
    }, time)
  }
}

let submitClick = dealFn(clickFn, 1000);

submitClick();
submitClick();
setTimeout(()=> {
  console.log("...");
  submitClick();
}, 1000);

擴充套件知識點

1、call 和 apply

詳見 javaScript---bind、call、apply

2、閉包

之所以在後續的方法呼叫(submitClick())時,能刪除之前呼叫時定義的 timer,是因為 js 的閉包,使得對於這些呼叫來說,timer 成為了一個“全域性變數”。

詳見 javaScript 中的閉包