防抖和节流

75 阅读2分钟

节流

有点类似于技能冷却中,使得一定时间内只触发一次函数,是通过判断是否到达一定时间来触发函数。按照一段时间的时间间隔来进行触发函数。

const throttle = (func, delay) => {
  let timer = 0
  return (...args) => {
    if(timer) {return} // 当前有任务,直接返回
    func.call(undefined, ...args)
      timer = setTimeout(()=> {
        timer = 0
      }, delay)
  }
}

const f1 = throttle(()=> {console.log('hello')}, 5000)


f1() // 打印 hello
f1() // 技能冷却中
// setInterval(()=> f1(), 500)

适用场景:

  • 拖拽:固定时间内只执行一次,防止超高频次触发位置变动。DOM 元素的拖拽功能实现(mousemove
  • 滚动:监听滚动scroll事件判断是否到页面底部自动加载更多
  • 动画:避免短时间内多次触发动画引起性能问题

防抖

有点类似于回城被打断将触发非常频繁的事件合并为一次去执行,在指定时间内只执行一次回调,如果在指定时间内又触发了,则回调的执行时间会基于此时刻重新开始计时。

const debounce = (func, wait = 50) => {
  // func 是用户传入需要防抖的函数
  // wait是等待时间,默认设为50ms
  let timer = null
  return (...args)=> {
    if(timer !== null){
      clearTimeout(timer) // 打断回城
    }
    // 重新回城
    timer = setTimeout(()=> {
      func.call(undefined, ...args) // 回调后调用 fn
    }, wait)
  }
}

const f1 = debounce(()=> {console.log('hello')}, 500)

f1() // 绑定到某一个事件上

具体实现,在Vue3演练场中尝试。

<script setup>
const debounce = (func, wait = 50) => {
  // func 是用户传入需要防抖的函数
  // wait是等待时间,默认设为50ms
  let timer = null
  return (...args)=> {
    if(timer !== null){
      clearTimeout(timer) // 打断回城
    }
    // 重新回城
    timer = setTimeout(()=> {
      func.call(undefined, ...args) // 回调后调用 fn
    }, wait)
  }
}

const f1 = debounce(()=> {console.log('hello')}, 500)

</script>

<template>
  <button @click="f1">点我</button>
</template>

适用场景:

  • 文本输入的验证,连续输入文字后发送 AJAX 请求进行验证,验证一次就好
  • 按钮提交:防止多次提交按钮,只执行最后提交的一次
  • 服务端验证:表单验证需要服务端配合,只执行一段连续的输入事件的最后一次

总结

防抖:限制执行次数,多次密集的触发只执行一次;

节流: 限制执行的频率,按照一个的时间间隔有节奏的执行。

防抖是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行