【前端幫幫忙】第7期 關於節流(throttle)和防抖(debounce)的理解

節流和防抖在咱們平時的項目中挺經常使用的,也是面試中常常會被提問的知識點,今天咱們一塊兒來學習一下。html

節流

簡單理解就是:控制函數每隔n秒執行一次。前端

做用

防止用戶高頻率的觸發事件,恰好這個事件又須要處理大量的計算和渲染而帶來的性能問題。面試

應用場景

  • onscroll
  • onresize
  • mousemove
  • touchmove
  • ...

示例

這邊咱們以onscroll來寫個例子,加深理解。瀏覽器

好比有這樣一個場景:咱們須要判斷瀏覽器滾動條滾動到底部的時候去動態加載一些數據,可能咱們直接就會寫上如下的代碼:bash

let obj = document.querySelector('.throttle-test');
let _count = 0;

obj.onscroll = function () {
  // 假設已經滾動到底部了,咱們給_count加1。
  _count++;
  console.log('執行次數:' + _count);
}
複製代碼

咱們來看下瀏覽器的打印結果,看如下gif圖:函數

能夠看到,函數執行了20次,很顯然這並非咱們想要的,由於onscroll事件並不會等你滾動到底部了再去觸發事件,而是會不間斷的觸發,這就很容易引起一些性能問題,這時候就須要用到節流了。性能

咱們把代碼作下修改:學習

let obj = document.querySelector('.throttle-test');
let _count = 0;
let _canRun = true;
obj.onscroll = function () {
  if (!_canRun) {
    return false;
  }
  _canRun = false;
  setTimeout(function () {
    // 假設已經滾動到底部了,咱們給_count加1。
    _count++;
    console.log('執行次數:'+_count);
    _canRun = true;
  }, 500);
}
複製代碼

經過如下gif圖,咱們能夠看到,函數最終只執行了2次。測試

經過一個定時器,咱們控制函數每隔500毫秒再執行一次,大大下降了執行頻率,從而提高性能。動畫

節流概念理解

節流跟防抖,它們既有類似之處但又有所不一樣,很容易混淆。這裏經過比喻來加深理解,先來講說節流。

節流的概念能夠想象一下水壩,你建了水壩在河道中,不能讓水流動不了,你只能讓水流慢些。換言之,你不能讓用戶的方法都不執行。(我的比較喜歡這個比喻,由於它很形象的說出了跟防抖的區別。)

防抖

控制函數在n秒內只能執行一次,若是用戶在n秒內重複的觸發事件,則從新計時且函數不會被執行,只有等到用戶再也不觸發事件的時候纔去執行一次。

做用跟節流相似,也是爲了防止用戶高頻率的觸發事件所引起的性能問題。

防抖概念理解

能夠想象一下作電梯,當有人進入電梯(觸發事件),那電梯將在10秒後出發(執行事件),這時若是又有人進入電梯了(在10秒內再次觸發了事件),咱們又得從新等10秒才能觸發(從新計時)。

示例

有個文本框讓用戶填寫用戶名,當用戶輸入字符時,咱們須要實時發請求到後臺去驗證用戶名是否有重複的。實際上,在加入防抖機制前,用戶輸入helloworld後,咱們已經發送了10次請求了,很顯然是不可取的。

看代碼:

let obj = document.querySelector('#testInput');  // 獲取文本輸入框
let _count = 0;

obj.onkeyup = function () {
  _count++;
  console.log('執行次數:' + _count);
}
複製代碼

咱們來給代碼加入防抖機制:

咱們只能假設用戶在停頓n秒內沒有再觸發事件,咱們就斷定用戶已經輸入完成了,這時再發送請求。

看代碼:

let obj = document.querySelector('#testInput');
let timer = null;
let _count = 0;

obj.onkeyup = function () {
  clearTimeout(timer);  // 清除定時器,從新計時
  timer = setTimeout(function () {
    _count++;
    console.log('執行次數:'+_count);
  }, 800);
}
複製代碼

經過動圖,能夠看到,當我一直輸入的時候,事件是不會被觸發的,直到我中止輸入纔會觸發一次。

實現思路:咱們把目標代碼放入到一個定時器裏,若是事件被頻繁的觸發,目標代碼將不會被執行。爲何不執行呢,由於咱們前面加了clearTimeout。至關於中途不斷的有人進入電梯,電梯又得從新倒計時10秒纔會啓動同樣,直到用戶沒再輸入了(沒人再進入電梯了),這時候目標代碼纔會按照咱們設定的時間再去執行一次(電梯纔會啓動)。

節流和防抖的區別

  • 節流:目標代碼會按照咱們設定的時間間隔即每隔n秒就執行一次
  • 防抖:在用戶不觸發事件時,纔去執行目標代碼,而且抑制了原本在事件中要執行的動做;當事件被一直觸發的狀況下,目標代碼有可能不會被執行
  • 函數節流會用在比input,keyup更頻繁觸發的事件中,如resize, touchmove, mousemove, scroll節流會強制函數以固定的速率執行。所以這個方法比較適合應用於動畫相關的場景。

最後

感謝您的閱讀,但願對你有所幫助。文中若是有描述不當的地方,煩請指正,感激涕零。 另外文中所演示的代碼僅用來測試使用,並不適合用在實際開發中,實際開發可使用Lodash庫中的節流防抖方法,這裏就不貼代碼了,畢竟考慮的比較全面哈。

Lodash庫的地址:

節流:www.lodashjs.com/docs/4.17.5…

防抖:www.lodashjs.com/docs/4.17.5…

關注

歡迎你們關注個人公衆號前端幫幫忙,一塊兒交流學習,謝謝~

參考: zhuanlan.zhihu.com/p/38313717

相關文章
相關標籤/搜索