防抖、节流

防抖和节流是性能优化策略,用于限制函数的高频执行。防抖确保在特定时间内只执行一次,常用于搜索建议输入框,避免过多请求。节流则在设定的时间间隔内保证执行一次,适用于文本框输入保存内容的场景,防止过度保存。本文详细介绍了防抖和节流的定义及实现方法。
摘要由CSDN通过智能技术生成

一、背景

防抖和节流都是为了限制函数高频执行而产生的概念,都属于性能优化的范畴。

举个例子,现在我们需要实现一个搜索建议的输入框,类似于百度首页的搜索功能

我们要怎么做呢?

<input id="search" />

function search () {
    ajax() // 访问后端接口
}
document.getElementById('search').onclick = search

正常流程是这个样子的,但是你会发现在你输入 browser 这个字母的过程中,前端一共发起了 7 次请求,这是完全没有必要的。实际上我们只需要一次查询就够了对吗?

二、防抖(debounce)

2.1 定义

对于短时间内连续触发的事件,防抖的意义在于,它可以让事件处理函数在某个特定的时间内只触发一次。就拿上面的例子来说,在你输入第一个字母和第二个字母之间的时间不超过 300ms 的话,就不执行查询操作,这样可以有效的减轻服务端的压力。

2.2 实现

既然需要“等一会”才执行事件处理函数,我们考虑使用 setTimeout 去实现它

let timer = null
document.getElementById('search').onclick = function () {
  if (timer) {
    clearTimeout(timer)
  }
  setTimeout(() => {
    search()
  }, 300)
}

 意思就是你输入一个字母,这里创建了一个异步任务,也就是 300ms 之后执行查询。但是 300ms 还没到呢,你有输入了一个字母,这时候前一个查询就没有意义了,可以取消它,再建一个新的异步任务。等了 300ms,你没有再输入新的内容了,那么最后创建的这个任务就会执行(前面的任务全被取消了)

优化、封装:上述写法产生了全局变量,不好不好!而且这种需求应该不止这一处会用到,我们考虑封装一个出一个防抖函数,以便其他地方不用再写这套逻辑了。

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

 有了 debounce 函数,上面的例子就可以写成这样

document.getElementById('search').onclick = debounce(search, 300)

三、节流(throttle)

3.1 定义

现在需求变了,input 变成了 textarea 文本框,我们要实现输入的过程中每隔 5s 保存一下内容。你可能会说,那简单啊!用 setInterval 啊!但是如果你输入了一段,然后构思了 5 分钟,那么这 5 分钟内还是在不停的执行保存,这就没有必要了。

那每次输入触发 onchange 都保存一下呢?那更恐怖了,一段文字可能要保存好几百次。那能不能在我一直快速输入的过程中(输入间隔一直小于 5s),还能每隔 5s 保存一次呢?并且当我停下来构思下一段的时候,“保存”这个动作就只能的停下来了呢?

节流就是为了解决这个问题而出现的

3.2 实现

function throttle (fn, delay) {
  let working = false
  return function () {
    if (working) {
      return
    }
    setTimeout(() => {
      fn()
      working = true
    }, delay)
  }
}

working 是一个标志位,异步任务是否处于工作当中。如果是,那么新触发的事件它将不予理睬,比如上面的例子我们可以这样实现

document.getElementById('search').onchange= throttle(save, 50000)

意思是 5s 之内我只执行一次保存,期间你触发了 onchange 我也不管。等到 5s 过了,你再触发 onchange 我就开启了新的一轮工作模式(持续 5s),新触发的事件我又不管了。等这个 5s 过去了,你也没再触发请求了,那我也就不会再执行保存操作了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>