javascript函数节流Throttle

335 阅读2分钟

学习目标

  1. 函数节流概念
  2. 函数节流的应用场景
  3. 函数节流实现
  4. 第三方库

定义

在单位时间内,只能触发一次函数。如果在这个单位时间内多次触发函数,都不会生效。 简单理解:就像王者荣耀里边,猴子的技能,你点了其中的一个技能,你就需要等待3秒,才能触发第二次。如果你在3秒内,又去点该技能,是不会生效的。

应用场景

  1. 鼠标不断点击触发,mousedown(单位时间内只触发一次),比如:表单提交
  2. 监听滚动事件,比如是否滑到底部自动加载更多

代码实现

  1. 时间差判断

触发事件时立即执行,以后每过delay秒之后才执行一次,并且最后一次触发事件若不满足要求不会被执行

function throttle(fn, delay) {
  let prev = 0;
  console.log(prev);
  return function (...args) {// 函数的参数
    const now = Date.now(); // 记录现在的时间
    if(now - prev >= delay) { // 如果间隔时间大于等于设置的节流时间
      console.log(1)
      fn.apply(this, args); // 修改内部函数的this指向
      prev = now;
    }
  }
}
  1. 定时器

第一次触发时不会执行,而是在delay秒之后才执行,当最后一次停止触发后,还会再执行一次函数。

function throttle(fn, delay) {
  let timer = null;
  return function(...args) {
    if(!timer){
      timer = setTimeout(() => {
        fn.apply(this, args);
        timer = null;
      }, delay);
    }
  }
}
  1. 时间差和定时器结合

第一次会马上执行,最后一次也会执行

function throttle(fn,delay) {
  let timer = null;
  let prev = 0;
  return function (...args) {
    const now = Date.now();
    // 触发间隔是否大于delay
    let remaining = delay - (now - prev);
    clearTimeout(timer);
    if (remaining <= 0) {
      fn.apply(this, args);
      prev = Date.now();
    } else {
      timer = setTimeout(() => {
        fn.apply(this, args)
      }, delay)
    }
  }
}

第三方库

  1. lodashjs
// 避免在滚动时过分的更新定位
jQuery(window).on('scroll', _.throttle(updatePosition, 100));
 
// 点击后就调用 `renewToken`,但5分钟内超过1次。
var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
jQuery(element).on('click', throttled);
 
// 取消一个 trailing 的节流调用。
jQuery(window).on('popstate', throttled.cancel);

  1. underscorejs
var throttled = _.throttle(updatePosition, 100);
$(window).scroll(throttled);