防抖函数和节流函数

防抖函数

防抖函数(debounce)可以使函数在n秒内触发重新计时,在此过程中不执行事件处理函数。
防抖函数在ajax请求数据、表单提交数据、输入验证等场景应用比较广泛。

下面模拟一个ajax请求数据的案例。

index.html

<button class="btn">获取数据</button>
<script type="text/javascript"
  src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>

index.js

var oBtn = document.getElementsByClassName('btn')[0];

oBtn.addEventListener('click', debounce(getDatas, 1000, true), false);

function getDatas () {
  $.ajax({
    url: 'https://api.apiopen.top/getJoke?page=1&count=2&type=video',
    type: 'GET',
    dataType: 'JSON',
    success: function (data) {
      console.log(data);
    },
    error: function (err) {
      console.log(err);
    }
  })
}

function debounce (fn, time, triggerNow) {
  var t = null;

  var debounced = function () {
    var _self = this,
        args = arguments;

      if (t) {
        clearTimeout(t);
      }

      if (triggerNow) {
        var exec = !t;

        t = setTimeout(function () {
          t = null;
        }, time);

        if (exec) {
          fn.apply(_self, args);
        }
      } else {
        t = setTimeout(function () {
          fn.apply(_self, args);
        }, time);
      }
  }

  debounced.remove = function () {
    clearTimeout(t);
    t = null;
  }

  return debounced;
}

节流函数

节流函数(throttle)是事件被触发后,n秒内只执行一次事件处理函数。
常用于JS动画等频繁触发的事件中,如resize,touchmove,mousemove,scroll等。

下面模拟一个输入验证的案例。

index.html

<input type="text" id="input" />

index.js

var oInput = document.getElementById('input');

oInput.onkeyup = throttle(check, 1000);

function check () {
  var val = this.value;

  if (val.length < 6) {
    console.log('invalid length');
  } else {
    console.log('success')
  }
}

function throttle (fn, delay) {
  var t = null,
      begin = new Date().getTime();

  return function () {
    var _self = this,
        args = arguments,
        cur = new Date().getTime();

    clearTimeout(t);

    if (cur - begin >= delay) {
      fn.apply(_self, args);
      begin = cur;
    } else {
      t = setTimeout(() => {
        fn.apply(_self, args);
      }, delay);
    }
  }
}