Debounce & Throttle

Debounce & Throttle

  • 最完整,必看,https://css-tricks.com/debouncing-throttling-explained-examples/

    • 有很多視覺化的 demo

    • 一般的 scroll 觸發頻率有可能達一秒三十次,在手機上甚至達到一秒一百次

    • 一句話說清楚,Debounce 就是把連續觸發的許多事件,只當作一次事件。

      • 實作上,可以是「立即觸發,忽略後面連續的一串事件」,也可以是「等一串事件發生後,只觸發一次」

      • 在 Lodash 就是 leading 和 trailing OPTIONS

    • 用得上的情境很多:視窗調整大小,keypress on autocomplete,資料驗證的提示

    • 作者建議直接使用 underscore 或 Lodash 的 code,並教你怎麼只取出你需要的那 2KB 的 code

      npm i -g lodash-cli
      lodash include = debounce, throttle
    • 使用時常犯的錯誤

    • // 錯誤用法
      $(window).on('scroll', function() {
         _.debounce(doSomething, 300); 
      });
      
      // 正確用法
      $(window).on('scroll', _.debounce(doSomething, 200));
    • 一句話說清楚,Throttle 就是確保每段間隔時間內只執行一次

      • 使用情境:無限捲動載入內容

    • 一句話說清楚,傳統的視覺更新常常用 setTimeout 或 setInterval,你可以改用原生的 requestAnimationFrame 來重繪畫面、更新動畫

  • 一個捲動 Debounce 的實例

  • // Source: https://github.com/wesbos/JavaScript30
    
    // Pre-Step: 這是用來讓 scroll 事件不要被觸發這麼多次,避免讓校能低落
    // LoDash 有提供這功能~
    function debounce(func, wait = 20, immediate = true) {
      var timeout;
      return function() {
        var context = this, args = arguments;
        var later = function() {
          timeout = null;
          if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
      };
    };
    // Step 1
    const sliderImages = document.querySelectorAll('.slide-in');
    
    // Step 2
    function checkSlide() {
      sliderImages.forEach(sliderImage => {
        // half way through the image
        const slideInAt = (window.scrollY + window.innerHeight) - sliderImage.height / 2;
        // bottom of the image
        const imageBottom = sliderImage.offsetTop + sliderImage.height;
        const isHalfShown = slideInAt > sliderImage.offsetTop;
        const isNotScrolledPast = window.scrollY < imageBottom;
        if (isHalfShown && isNotScrolledPast) {
          sliderImage.classList.add('active');
        } else {
          sliderImage.classList.remove('active');
        }
      });
    }
    
    // Step 1
    window.addEventListener('scroll', debounce(checkSlide));
  • 視覺化小例子,精簡快速結論,http://jsfiddle.net/missinglink/19e2r2we/

  • Lodash 的 Debounce 與 throttle,https://lizhiyao.github.io/2017/02/15/debounce-throttle/

    • 簡中,讀起來比較快。有簡單的程式

Last updated