js---節流

前言

在活動需求中,由於作的狂點小遊戲。在實際體驗中就會出現,頻繁的點擊形成動畫的不連貫,影響用戶體驗。而且再播放音效的時候,若是沒點擊一次就觸發一次音效會形成將聲音壓入到棧中,會持續的播放。所以在這裏的操做作了節流的限制,隔多少秒觸發一次。總結一下節流的實現方法。javascript

節流

節流的原理很簡單:若是你持續觸發事件,每隔一段時間,只執行一次事件。
根據首次是否執行以及結束後是否執行,效果有所不一樣,實現的方式也有所不一樣。
節流的實現方式有兩種主流的實現方式,一種是時間戳,一種是設置定時器。java

使用時間戳

本次活動利用的就是該實現方式。
使用時間戳,當觸發事件的時候,咱們取出當前的時間戳,而後減去以前的時間戳(最一開始值設爲0),若是大於設置的時間週期,就執行函數,而後更新時間戳爲當前的時間戳,若是小於就不執行。
具體代碼以下:app

function throttle(fun, wait) {
       var context,args;
       var previous = 0;
       return function () {
           var now = +new Date();//格式化時間
           context = this;
           args = arguments;
           if(now - previous > wait){
               fun.apply(context,args);
               previous = now;
           }
       }
   }

這樣寫法適用於,將要執行的函數直接賦值給事件。btn.addEventListener('click',throttle(addSelf,2000),false);由於throttle返回的是一個函數,直接賦值給事件能夠觸發執行。函數

若是在事件的回調中執行,就要具體修改一下。

var previous = 0;
function throttle(fun, wait) {
       var context,args;
       return function () {
           var now = +new Date();//格式化時間
           context = this;
           args = arguments;
           if(now - previous > wait){
               fun.apply(context,args);
               previous = now;
           }
       }
   }

將previous提高到外面,寫法就改成btn.addEventListener('click',function () {動畫

throttle(addSelf,2000)();
},false);
這時throttle函數在後面要加小括號直接執行。

使用定時器

當觸發事件的時候,咱們設置一個定時器,再觸發事件的時候,若是定時器存在,就不執行,直到定時器執行,而後執行函數,清空定時器,這樣就能夠設置下個定時器。this

function throttle(fun, wait) {
      var timeout context,args;
      return function () {
          context = this;
          args = arguments;
          if(!timeout){
              timeout = setTimeout(function () {
                timeout = null;
                fun.apply(context,args)
              },wait)
          }
      }
  }

同理若是用在回調函數中,須要將timeout提到函數外面。
使用定時器有個問題就是點擊不會當即執行,須要延遲設定的時間纔會執行。code

比較

  • 1.第一種事件會當即執行,第二種事件會在n秒後第一次執行
  • 2.第一種事件中止觸發後沒有辦法再執行事件,第二種事件中止觸發後依然會再執行一次事件

結合這兩種方法,而且能夠配置是否要第一次當即執行或者中止觸發後再執行一次。

直接上代碼遊戲

  • 配置第三個參數leading:false代表不須要第一次當即執行。trailing:false代表中止觸發後再也不執行最後一次。
var previous = 0;
    var timeout;
    function throttle(fun, wait, options) {
     var context,args;
     /*var previous = 0;*/
     if(!options) options = {};

     var later = function () {
         previous = options.leading === false ? 0 :new Date().getTime();
         timeout = null;
         fun.apply(context,args);
         if(!timeout) context = args = null;
     };

     var throttled = function () {
         var now = new Date().getTime();
         if(!previous && options.leading === false) previous = now;
         var remaining = wait - (now - previous);
         context = this;
         args = arguments;
         if(remaining <= 0 || remaining > wait) {
             if(timeout){
                 clearTimeout(timeout);
                 timeout = null;
             }
             previous = now;
             fun.apply(context,args);
             if(!timeout) context = args = null;
         } else if(!timeout && options.trailing !==false){
            timeout = setTimeout(later,remaining)
         }
     };
     return throttled;
 }
 //使用 
 btn.addEventListener('click',function () {
        throttle(addSelf,2000,{trailing:false})();
    },false);

默認狀況下都是兼顧了第一次點擊當即觸發和最後觸發後執行一次。事件

注意

  • leading:false和trailing:false不能同時設置。
  • 若是同時設置的話,好比當你在再也不點擊的時候,由於trailing設爲了false,中止觸發不會設置定時器,因此只要再過了設置的時間,在點擊的話,就會當即執行,就違反了leading:false了。因此該方法只有三種狀況可用。
相關文章
相關標籤/搜索