节流和防抖傻傻分不清楚?

61 阅读5分钟

防抖节流

函数节流(throttle)

规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。

节流是指绑定事件后,通过动作触发事件,在这段时间内,如果动作又发生,忽略该动作,一直到事件执行完后才能重新触发。通俗的说就是控制高频执行的次数。

节流应用场景

节流适合大量事件按时间做平均分配触发。

  • 还有一个就是像掘金写文章这里一样,有自动保存功能,我们一边写,它可以一边间隔性地保存。
  • 剩下就比如说 DOM 元素拖拽,以及游戏中的刷新率都是会使用到节流函数的。

手写函数节流

			// 需求: 1. 鼠标在盒子里面滑动,让盒子里面的数字累加
			// 需求: 2. 封装节流函数throttle, 将mouseMove进行包装
			// 需求: 3. 有间隔的调用mouseMove函数,然我们的页面每个固定时间累加
const boxDom = document.querySelector('.box')
let count = 1

function mousemove() {
  count++
  boxDom.innerHTML = count
}

// 节流throttle-是函数, 是一个优化函数执行的流程, 减少代码不必要的执行,提升性能
function throttle(fn, time) {
  // 节流throttle注意点:
  // 1.节流函数一定要有返回值, 并且返回值是一个函数
  // 2.要用节流, 就必须有 开始时间  当前时间(结束时间)
  let startTime = +new Date() // 开始时间
  return function () {
    let currentTime = +new Date() // 结束时间(最后的时机)
    if (currentTime - startTime > time) {
      //就是我们的当前时间和 开始时间相减,如果结果大于间隔时间,就可以进行下一步的函数执行这个判断条件意思是,如果鼠标两次滑动的时间大于1秒钟才会调用fn,如果鼠标两次滑动的时间太快,小于1秒钟,就不让fn执行.
      fn()
      startTime = currentTime // 每次滑动以后,将最后的时间 从新赋值给 开始时间
    }
  }
}

//绑定事件, mouseMove 是用户一滑动就会执行,(但用户滑的太快会造成性能浪费,所以我们要给用户的鼠标滑动再设置一个条件,用节流规定两次操作的间隔时间,大于这个间隔时间才执行)
// boxDom.addEventListener('mousemove', mousemove)
boxDom.addEventListener('mousemove', throttle(mousemove, 1000))

个人理解 函数防抖就是法师发技能的时候要读条,技能读条没完再按技能就会重新读条。

函数防抖(debounce)

顾名思义,我们可以将防抖理解为是防止抖动。当我们在频繁地触发一个事件时,会引起不必要的性能损失,那么我们需要做的是让事件在停止触发后再触发,以此减少性能损失。

防抖就是要延迟执行,我们一直操作触发事件并且不执行,只有当停止操作后等才会执行。

在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。只有当停止操作后才会执行

防抖应用场景

防抖适合多次事件一次响应的情况。

  • 比较典型的有search搜索联想,用户在不断输入值时,用防抖来节约请求资源。加入了防抖以后,当你在频繁的输入时,并不会发送请求,只有当你在指定间隔内没有输入时,才会执行函数。如果停止输入但是在指定间隔内又输入,会重新触发计时。
  • 还有按钮点击事件,为了防止用户多次重复提交也会使用防抖函数。
  • 最后就是部分的电话号码输入的验证,要等停止输入后才会进行一次验证。

手写函数防抖

const boxDom = document.querySelector('.box')

let count = 1

function mousemove() {
  count++
  boxDom.innerHTML = count
}

// 防抖 debounce (辅助理解节流)
// 节流 throttle(工作重点)  --- 因为工作里面,我们会用lodash, lodash里面的防抖和节流就叫这个名字

// 思想:将一些变量,全部换成函数的形参, 通过外面传递参数进来,再写代码
function debounce(fn, time) {
  let timerId
  return function () {
    // console.log(1111)
    // 下一次滑动开始之前,要先将之前的定时器清除,不然的话一直滑动一直生成定时器,多个定时器叠加在一起.
    clearTimeout(timerId)

    // 定时器里面的函数,需要2S种以后才会执行,
    // 如果滑动太快,2秒以内,又滑动了我们的鼠标,就会进入函数debounce(fn, time){}, 首先清空上一次的定时器
    // 只有当两次滑动的间隔,大于了2s, 定时器里面的回调函数才会执行
    timerId = setTimeout(function () {
      fn()
    }, time)
  }
}

// boxDom.addEventListener('mousemove', mousemove)
// 往高级前端发展, 就要学会 将函数作为参数, 以及将函数作为返回值!!!
boxDom.addEventListener('mousemove', debounce(mousemove, 1000))
// boxDom.addEventListener('mousemove', function() {
//   mousemove()
// })
//这个代码和上面一样

不管我们速度多块,总是1秒内只执行一次。

个人理解 函数节流就是fps游戏的射速,就算一直按着鼠标射击,也只会在规定射速内射出子弹。

总结对比

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