防抖(debounce)和截流(throttle)

539 阅读1分钟

限制接口访问一般涉及到用户的输入。主要有两个经典场景:debounce 强制函数在某段时间内只执行一次,throttle 强制函数以固定的速率执行。 对比demo

  1. 使用 debounce(防抖) codepen.io/llh911001/p…
const debounce = (fn, delay: number) => {
  let inDebounce;
  return function(...args) {
    const context = this;
    clearTimeout(inDebounce);
    inDebounce = setTimeout(() => {
      fn.apply(context, args);
    }, delay);
  };
};

export default debounce; 2. 使用 throttle (截流) codepen.io/llh911001/p…

function throttle(fn, threshold) {
  // 记录上次执行的时间
  var last
  // 定时器
  var timer
  // 默认间隔为 250ms
  threshold || (threshold = 250)
  // 返回的函数,每过 threshold 毫秒就执行一次 fn 函数
  return function () {
    // 保存函数调用时的上下文和参数,传递给 fn
    var context = this
    var args = arguments
    var now = +new Date()
    // 如果距离上次执行 fn 函数的时间小于 threshold,那么就放弃
    // 执行 fn,并重新计时
    if (last && now < last + threshold) {
      clearTimeout(timer)
      // 保证在当前时间区间结束后,再执行一次 fn
      timer = setTimeout(function () {
        last = now
        fn.apply(context, args)
      }, threshold)
    // 在时间区间的最开始和到达指定间隔的时候执行一次 fn
    } else {
      last = now
      fn.apply(context, args)
    }
  }
}
  1. debounce.leading(先执行再防抖) vs debounce.trailing(先防抖再执行:)

先执行再防抖: debounce.leading demo: codepen.io/dcorb/pen/G…

先防抖再执行: debounce.trailing demo: codepen.io/dcorb/pen/K…

function debounce(func, wait, immediate) {
	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);
	};
};