函数防抖和节流

262 阅读3分钟

研究了半天的函数防抖和节流,其实也没有多难,今天简单总结一下。

函数防抖和节流分别是什么

函数防抖和节流都是为了函数频繁调用而做的性能优化,例如在一些会频繁触发的事件如 mousemove、resize、scroll、keypress、input等,这类事件高频触发从而不断调用其回调函数。

函数防抖和节流的思想很相似,主要在于是第一次触发还是最后一次触发为准,它们都有一个等待的时间,函数防抖是指第一次触发后,如果在等待的时间内再次触发,那么就会重新计时,再次等待相同的时间后触发执行,而函数节流是指第一次触发后,如果在等待的时间内再次触发,那么该触发并不会执行,只有等待的时间结束后再次触发才会重新执行,这就相当于游戏中的技能冷却时间,在冷却时间再次触发技能是没有用的。

函数防抖和节流的实现

函数防抖代码实现

下列代码中运用了 keyup 事件,使用函数防抖的思想减少了频繁触发 keyup 事件时调用函数执行的次数。可以模拟当用户在输入框中输入内容然后发起 AJAX 请求的真实场景,这样做可以减少请求的次数。

function debounce(fn, delay) {
    let timerId = null; //运用闭包保存状态
    return function() {
      let that = this
      let args = arguments
      if (timerId) { //如果已经执行,那么就清除之前的执行状态,重新执行
        window.clearTimeout(timerId)
      }
      timerId = setTimeout(() => {
        fn.apply(that, args)
        timerId = null
      }, delay)
    }
  }
  //执行的函数
function callback(content) {
  console.log(content)
}

let debounced = debounce(callback, 500);

let input_debounce = document.getElementById('debounce')

input_debounce.addEventListener("keyup", e => {
  debounced(e.target.value)
})

函数节流代码实现

在下列代码中,虽然调用了两次回调函数,但是只执行了一次,因为只有在相应的时间段后才将 canuse 设置为 true,canuse 是一个是否应该执行的状态变量。

function throttle(fn, delay) {
  let canuse = true;
  return function() {
    if (canuse) {
      canuse = false;
      fn.apply(this, arguments);
      setTimeout(() => { //一段时间内再将 canuse 设置为 true,避免在等待时间内再次执行
        canuse = true;
      }, delay)
    }
  }
}

function callback(content) {
  console.log(content)
}
let throttled = throttle(callback, 500);

throttled("hello");
throttled("hello");

下列代码运用 mousemove 事件来模拟频发触发,然后在频发触发的情况下利用时间的间隔来控制是否应该执行回调函数,也就是在当前的时间和上一次触发函数的时间之差大于等待时间的情况下才会执行回调函数。

function throttle(fn, delay) {
  let previous = 0;
  return function() {
    let now = new Date();
    let actual_delay = now - previous;
    if (actual_delay > delay) {
      previous = now;
      fn.apply(this, arguments);
    }
  }
}

function callback(content) {
  console.log(content);
}

let throttled = throttle(callback, 3000)

document.onmousemove = () => {
  throttled("回调每三秒钟才被触发")
}

函数防抖和节流的使用场景

函数防抖的使用场景

1.搜索框搜索输入,只有在用户最后一次输入后再发起请求。

2.手机号、邮箱输入完成后再进行验证。

3.使用 resize 调整窗口大小的时候,只有当用户不再调整的时候再重新渲染页面上的内容。

函数节流的使用场景

1.当用户滚动页面的时候隔一段时间后再重新加载数据,而不是只要有滚动就去重新加载数据。

2.搜索框的联想功能。

3.用户频繁点击提交或者频繁提交表单。