javascript中的函數節流和函數去抖

來源:互聯網
上載者:User

標籤:time()   監聽   問題   under   佔用   last   函數   像素   文字   

帶著問題去嘗試

首先我們要知道為什麼要用到函數節流和函數去抖?我們帶著以下的疑問來進行分析!

1.比如搜尋方塊,你會用到什麼事件(change、blur、keyup等)?去做什麼效果?
2.再比如scroll滾動事件,怎麼去觸發?是滾一段距離觸發一次?還是滾一圈觸發一次?還是滾一次觸發一次?
3.還包括mouseover事件是怎麼觸發呢?
......

情境執行個體

 

函數節流和去抖的出現情境,一般都伴隨著用戶端 DOM 的事件監聽。舉個例子,實現一個原生的拖拽功能(不能用 H5 Drag&Drop API),需要一路監聽 mousemove 事件,在回調中擷取元素當前位置,然後重設 dom 的位置(樣式改變)。如果我們不加以控制,每移動一定像素而觸發的回調數量是會非常驚人的,回調中又伴隨著 DOM 操作,繼而引發瀏覽器的重排與重繪,效能差的瀏覽器可能就會直接假死,這樣的使用者體驗是非常糟糕的。我們需要做的是降低觸發回調的頻率,比如讓它 500ms 觸發一次,或者 200ms,甚至 100ms,這個閾值不能太大,太大了拖拽就會失真,也不能太小,太小了低版本瀏覽器可能就會假死,這樣的解決方案就是函數節流,英文名字叫「throttle」。函數節流的核心是,讓一個函數不要執行得太頻繁,減少一些過快的調用來節流。

 

說完函數節流,再看它的好基友函數去抖(debounce)。思考這樣一個情境,對於瀏覽器視窗,每做一次 resize 操作,發送一個請求,很顯然,我們需要監聽 resize 事件,但是和 mousemove 一樣,每縮小(或者放大)一次瀏覽器,實際上會觸發 N 多次的 resize 事件,用節流?節流只能保證定時觸發,我們一次就好,這就要用去抖。簡單的說,函數去抖就是對於一定時間段的連續的函數調用,只讓其執行一次。

 

執行個體瞭解

下面就讓我們來瞭解throttle(節流) 和 debounce(去抖)

1.throttle節流,scroll和mouseover亦或者其他方式,每次移動都會觸發代碼效果,但是這些效果太密集了,佔用了系統資源,電腦的計算能力是有限的,我們寫的代碼應該儘可能的優雅。
2.debounce去抖,本意是從按鍵去抖過來的,讓我們的使用者正確的操作之後才去執行代碼,且只會執行一次,比如當我們做文本輸入的時候,如果用keyup我們不是去節流,而是去判斷使用者停止了輸入。
3.節流保證在一定時間內,只能觸發一次。如果我們只要觸發一次,這就是去抖。代碼上來看差距不是很大。

直接試一下:

//先來個有問題的代碼window.onscroll=function(){    console.log(new Date());}

 

控制台會列印:

VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中國標準時間)VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中國標準時間)VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中國標準時間)VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中國標準時間)VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中國標準時間)VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中國標準時間)
...

控制台會一直這樣輸入,那問題來了,這擷取並不是我們想要的,我們並不想讓他一直觸發下去。

我們要解決這些問題,所以直接看代碼:

//我們先來個節流,每秒輸出一次window.onscroll=function(){    if(window.onScrollTag == undefined){        window.onScrollTag=true;        console.log(new Date());        setTimeout(function(){            window.onScrollTag=undefined;        },1000);    }}//先觸發window.onscroll=function(){    if(window.onScrollTag == undefined){        window.onScrollTag=setTimeout(function(){            window.onScrollTag=undefined;             console.log(new Date());        },1000);           }}//後觸發//從上面的代碼可以看出來,我們在一個事件執行的時候就把標記改成不可用。一秒後才可以再次觸發操作。//我們在嘗試一下去抖window.onscroll=function(){    if(window.onScrollTag != undefined){        clearTimeout(window.onScrollTag);    }    window.onScrollTag=setTimeout(function(){         console.log(new Date());    },1000);}//消抖,消除抖動,感覺這個更好聽
//節流funtion throttle(func, wait) {      var lastTime = 0,        timeout;      return funtion() {            var context = this,            args = arguments,            delay = wait || 100,            now = new Date().getTime();            if (now - lastTime <= delay) {                  return;            }            lastTime = now;        clearTimeout(timeout);          timeout = setTimeout(function() {            timeout = null;            func.apply(context, args);        }, delay)      }}// 去抖function debounce(func, wait) {    var timeout;    return function() {        var context = this,            args = arguments,            delay = wait || 250;        clearTimeout(timeout);        timeout = setTimeout(function() {            timeout = null;            func.apply(context, args);        }, delay);    };}

 

throttle 應用情境

函數節流有哪些應用情境?哪些時候我們需要間隔一定時間觸發回調來控制函數調用頻率?

  • DOM 元素的拖拽功能實現(mousemove)
  • 射擊遊戲的 mousedown/keydown 事件(單位時間只能發射一顆子彈)
  • 計算滑鼠移動的距離(mousemove)
  • Canvas 類比畫板功能(mousemove)
  • 搜尋聯想(keyup)
  • 監聽滾動事件判斷是否到頁面底部自動載入更多:給 scroll 加了 debounce 後,只有使用者停止滾動後,才會判斷是否到了頁面底部;如果是 throttle 的話,只要頁面滾動就會間隔一段時間判斷一次
debounce 應用情境

函數去抖有哪些應用情境?哪些時候對於連續的事件響應我們只需要執行一次回調?

  • 每次 resize/scroll 觸發統計事件
  • 文本輸入的驗證(連續輸入文字後發送 AJAX 請求進行驗證,驗證一次就好)
小結

函數節流和函數去抖的核心其實就是限制某一個方法被頻繁觸發,而一個方法之所以會被頻繁觸發,大多數情況下是因為 DOM 事件的監聽回調,而這也是函數節流以及去抖多數情況下的應用情境

如果大家感興趣,可以參考下:http://underscorejs.org/ 

 

javascript中的函數節流和函數去抖

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.