防抖和节流知多少

1,308 阅读2分钟

防抖

在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新再等n秒在执行回调。

例子

//模拟一段ajax请求
function ajax(content) {
  console.log('ajax request ' + content)
}

let inputa = document.getElementById('unDebounce')

inputa.addEventListener('keyup', function (e) {
    ajax(e.target.value)
})

看一下运行结果: 1111.gif

可以看到,我们只要按下键盘,就会触发这次ajax请求。不仅从资源上来说是很浪费的行为,而且实际应用中,用户也是输出完整的字符后,才会请求。下面我们优化一下:

//模拟一段ajax请求

  function ajax(content) {
     console.log('ajax request' + content)
  }
  function debounce(fn, delay) {
    let timer;
    return function () {
      let context = this;
      const args = [...arguments];
      if (timer) {
        clearTimeout(timer);
      }
      timer = setTimeout(() => {
        fn.apply(context, args);
      }, delay);
    };
  }
  let dedebounceajax =  debounce(ajax,1000);
  var inputs = document.getElementById('inputs')
  inputs.addEventListener("keyup",(e)=>{
      dedebounceajax(e.target.value)
  })

看一下运行结果:

2222.gif

可以看到,我们加入了防抖以后,当你在频繁的输入时,并不会发送请求,只有当你在指定间隔内没有输入时,才会执行函数。如果停止输入但是在指定间隔内又输入,会重新触发计时。

节流

规定在一个单位时间内,只能触发一次函数。 假设你点击一个按钮规定了5秒生效,不管你在5秒内点击了按钮多少次,5秒只会生效一次。

例子

// 时间戳箭头函数版本 节流函数

function throttle(func, wait) {
    let timer = 0;
    return (...rest) => {
      let now = Date.now();
      let that = this;
      if (now > timer + wait) {
        fn.apply(that, rest);
        timer = now;
      }
    };
}

// 定时器版本 节流函数

function throttle(func, wait) {
    let timeout;
    return function() {
        let context = this;
        let args = arguments;
        if (!timeout) {
            timeout = setTimeout(() => {
                timeout = null;
                func.apply(context, args)
            }, wait)
        }

    }
}

let throttleAjax = throttle(ajax, 1000)
let inputc = document.getElementById('throttle')
inputc.addEventListener('keyup', function(e) {
    throttleAjax(e.target.value)
})

看一下运行结果:

3333.gif

可以看到,我们在不断输入时,ajax会按照我们设定的时间,每1s执行一次。

总结

  • 函数防抖和函数节流都是防止某一时间频繁触发,但是这两兄弟之间的原理却不一样。
  • 函数防抖是某一段时间内只执行一次,而函数节流是间隔时间执行。

应用场景

防抖应用场景

  • input框搜索,用户在不断输入值时,用防抖来节约请求资源。
  • window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次。

节流应用场景

  • 鼠标不断点击触发,mousedown(单位时间内只触发一次)
  • 监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断