函数的防抖与节流

136 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

有时候当我们在面试的时候,面试馆会问:“你知道防抖吗?”在刚开始学习的时候,一脸懵逼防抖时候什么鬼?后来进过面试和自己的一一些工作经验发现,防抖和节流是非常常见的。

防抖

首先有这样一个需求,在输入框输入内容结束后向后端发送数据,当我们不停的输入时,发现会一直往后端发送数据,此时太消耗性能,于是产生了防抖函数。

QQ截图20220610213317.jpg

在函数触发n秒内,函数再次被触发,那么会重新计算函数执行时间 场景有:input输入框提交数据,window窗口size大小改变

非立即执行版

 let inputBtn = document.getElementById('btn')
  inputBtn.addEventListener("keyup",(e) => {
    input(e.target.value)
  })

  function submit(val) {
    console.log('给后端传送数据',val)
  }


  function debounce(fn,delay) {
    let timer = null
    return function() {
      if(timer) clearTimeout(timer)
      timer = setTimeout(() => {
        fn.apply(this,arguments)
      },delay)
    }
  }

  let input = debounce(submit,3000)

立即执行版

上一个版本是当第一次输入的时候就会产生延时的效果,如果在第一次执行完后延迟了3s发送数据,此时网络又比较慢,那么等数据响应完后中间时间差隔太大,很有可可能会造成用户的流失,接下来改进一下,在用户输入完后会立马发送数据。

触发事件后函数会立即执行一次,然后 n 秒内再次触发事件不继续执行函数的效果

function debounce(fn,delay) {
    let timer = null
    return function() {
      // 立即执行的开关
      let firstSubmit = !timer

      if(timer) clearTimeout(timer)

      if(firstSubmit) {
        fn.apply(this,arguments) 
      }
      timer = setTimeout(() => {
        timer = null
      },delay)

    }

}

节流

在n秒内函数只执行一次 场景:

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

定时器版本

function throttle(fn,delay){
  let timer
  return function() {
    if (timer) {
      return
    }
    timer = setTimeout(() => {
      fn.apply(this,arguments)
      timer = null
    },delay)
  }
}

时间戳版本

function throttle(fn,delay) {
  let pre = 0

  return function () {
    let now = new Date().now()

    if(now - pre > delay) {
      fn.apply(this,arguments)
      pre = now
    }
  }
}