防抖,节流

218 阅读2分钟

在做JavaScript交互中,我们经常会需要监听一些容易频繁触发的事件。比如键盘、scroll事件、resize事件、input事件。如果每次事件触发都去执行对应的回调函数的话,会导致回调函数的频繁执行。假如我们在回调函数里做了异步请求,就会频繁的请求后台,导致了页面上很多异步请求的堆积,也加重了服务器端的压力。这种情况下,我们需要做一些处理,以避免回调函数过于频繁的执行。防抖可以有效的解决这个问题。

防抖 -- 防止回调函数的频繁执行。

/*
 * func: 真正执行的函数
 * wait: 规定的多久时间会调用func
 * immediate: true,立即触发执行,在间隔小于wait都不再触发。false或者不传,不会立即触发,在间隔大于wait时会触发一次。
*/
function debounce(func, wait, immediate) {
  // 作为闭包访问的变量,一直处在外层作用域中,保存setTimeout返回的id。
  var timeout;
  return function() {
    var args = arguments;
    var context = this;
    var later = function() {
      timeout = null;
      if (!immediate) {
        func.call(context, args);
      }
    };
    var callNow = immediate && !timeout;
    // 如果在指定的wait时间内清除timeout,以达到不执行func函数。
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) {
      func.call(context, args);
    }
  };
}

节流函数最主要的不同在于,规定了在指定时间内至少会执行一次回调函数。比如在图片的懒加载中,我们不希望在滚动开始或者停止时执行一次加载,我们希望的是在滚动中不断的加载图片。

节流 -- 保证在 X 毫秒内至少执行一次回调函数

function throttle(func, wait, mastRun) {
  var timeout,
      startTime = Date.now();
  return function() {
    var args = arguments,
        context = this;
        curTime = Date.now();
    clearTimeout(timeout);
    // 如果达到了规定的触发时间
    if (curTime - startTime >= mastRun) {
      func.call(context, args);
      startTime = Date.now();
    } else {
      timeout = setTimeout(func, wait);
    }
  }
}