防抖和节流

一、什么是防抖和节流

比如搜索框,用户在输入的时候使用change事件去调用搜索,如果用户每一次输入都去搜索的话,那么消耗的服务器资源就太大了。

1.防抖 - debounce

其中一种解决方案就是每次用户停止输入后,延迟超过xxxms时,才去搜索,这就是防抖。

原理:将若干个函数调用合成为一次,并在给定时间过去之后仅被调用一次。

    var num = 1
    var content = document.getElementById('content')
    function count() {
      content.innerHTML = num++
    }

    const debounce = (func, wait) => {
      let timer // 维护一个timer,用来记录当前执行函数状态
      return function () {
        // 通过this 和 arguments 获取函数的作用域和变量
        let context = this
        var args = arguments
        if (timer) {
          clearTimeout(timer) // 清理掉正在执行的函数,并重新执行
        }
        timer = setTimeout(() => {
          console.log(context)
          func.apply(context, args)
        }, wait)
      }
    }

    content.onmousemove = debounce(count, 1000)

debounce函数封装后,返回内部函数

每一次事件被触发,都会清除当前的timer然后重新设置超时并调用。这会导致每一次高频事件都会取消前一次超时调用,导致事件处理程序不能被触发

只有当高频事件停止,最后一次事件触发的超时调用才能在wait时间后执行。

2.节流 - throttle

另一种解决方案比防抖要宽松些,这时我们不想用户一味的输入,而是给用户一些搜索提示,所以在当中限制每过xxxms就查询一次此时的String,这就是节流。

原理:节流函数不管事件触发有多频繁,会被保证在规定时间内一定会执行一次真正的事件处理函数。

代码实现有两种,一种是时间戳,另一种是定时器

1) 时间戳实现:

    const throttle = (func, wait) => {
      let pre = 0
      return function () {
        let context = this
        let args = arguments
        let now = Date.now()
        if (now - pre >= wait) {
          func.apply(context, args)
          pre = Date.now()
        }
      }
    }

当高频事件触发时,第一次会立即执行(给事件绑定函数与真正触发事件的间隔如果大于wait的话),而后再怎么频繁触发事件,也都是会没wait秒才执行一次。而当最后一次事件触发完毕后,事件也不会再被执行了。

2) 定时器实现:

当触发事件的时候,我们设置一个定时器,再触发事件的时候,如果定时器存在,就不执行;知道wait秒后,定时器执行执行函数,清空定时器,这样就可以设置值下个定时器。

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

当第一次触发事件时,肯定不会立即执行函数,而是在wait秒后才执行。

之后连续不断触发事件,也会每wait秒执行一次。

当最后一次停止触发后,由于定时器的wait延迟,可能还会执行一次函数。

3)综合使用时间戳与定时器,完成一个事件触发时立即执行,触发完毕还能执行一次的节流函数。

    function throttle(func, wait, type) {
      if (type === 1) {
        var previous = 0
      } else if (type === 2) {
        var timer
      }
      return function () {
        var context = this
        var args = arguments
        if (type === 1) {
          var now = Date.now()
          if (now - previous >= wait) {
            func.apply(context, args)
            previous = now
          }
        } else if (type === 2) {
          if (!timer) {
            timer = setTimeout(() => {
              timer = null
              func.apply(context, args)
            }, wait)
          }
        }
      }
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值