节流和防抖

阅读 1.9k
标签: JavaScript

在前端开发中,有时为了性能考虑,会限制在某一段时间内频繁执行的任务的次数,防止程序开销过大引发卡顿或崩溃的情况,一种常用的手段就是节流和防抖。但这两者颇有些相似,导致一些初学者常常弄混,导致用错,本篇将对这两者的概念进行区分和说明。

节流

有一个成语,叫开源节流,这里节流的意思是指节省开支,那如何节省开支呢?拿我们日常生活中的例子来说,假如一个家庭每周都会去电影院消费一次,但由于最近丈夫失业,导致收入巨减,为了平衡收支,家庭成员决定,不能每周去电影院消费了,改为每月去一次。通过这样的方式来减少了日常开支,达到节流的目的。

对于程序中的节流而言,其目的和功能是一样的,我们来看一个例子:

<div id="myDiv"
    style="height: 150px; line-height:150px; text-align:center; color: #fff; background-color:#ccc; font-size:80px;">
</div>

JavaScript代码如下:

let num = 1
const content = document.getElementById('myDiv')

function count() {
    content.innerHTML = num++
}

content.onmousemove = count

在上述代码中,div 元素绑定了 mousemove 事件,当鼠标在 div 区域移动的时候,会持续地去触发事件,导致频繁执行count函数。假如count函数是一个开销很大的任务,那么如此频繁的执行很可能导致页面卡顿甚至崩溃,为了解决这个问题,那么,节流就派上用场了:

<script src='./lodash.min.js'></script>

content.onmousemove = _.throttle(count, 2000)

也就是说,不管鼠标在 div 区域移动如何快速移动,每2s内只会执行一次count函数。这么说吧,如果鼠标一直在div 区域移动,之前10s内可能会执行count函数500次左右(大约20ms执行一次),而节流后,只会执行5次了,开销减少了100倍。

总结一下,所谓节流,就是指连续触发事件,但是在 n 秒中只执行一次函数。

防抖

先来说说什么是抖动,不知道大家坐过那种减震效果不好的拖拉机或者公交车没有,尤其是当司机起步时,那种持续的抖动感,那就是抖动,也就是说,在一段时间内,会持续而频繁地执行一些动作。那么防抖呢?就是要防止这么频繁的抖动,那要怎么做呢?

可以设置一种过滤抖动的装置,限制抖动的频率,比如,在2s内最多让它抖动一次,有人可能疑惑了,这看上去不是和节流一样吗?其实不然,还是上面的例子,我们来看看防抖:

content.onmousemove = _.debounce(count, 2000)

用了防抖后,如果在2s内一直有鼠标在移动,那么必须等待最后一次移动延迟2s后,才会执行count函数,比如,在开始时鼠标移动了一次,在1.5s时鼠标又移动了一次,那么在3.5s时才会执行第一次count函数;如果在开始时鼠标移动了一次,在1.5s时鼠标又移动了一次,之后,在3.4s时鼠标又再次移动了一次,那么在第5.4s时才会执行第一次count函数。

对比够明显了吧,可以说,防抖是一种更严格的节流形式。

实际应用

明白了节流和防抖的区别后,那么在前端开发的实际应用中,什么时候用节流,什么时候用防抖呢?

我们来看一个场景,如果需要在滚动页面时执行一项开销较大的任务,因为滚动时会频繁触发onscroll事件,导致该任务被频繁执行,引起了页面的卡顿,为了减少触发次数,提高性能,那使用节流或者防抖都可以达到提高性能的目的。

但如果除了提升性能外,还需要记录用户稳定滚动的次数,比如1s内用户没有再次滚动才算一次,那么,就只能使用防抖来做了。

另外,一种常用的使用防抖的场景是,当用户在input框中输入字符进行后端查询时,如果每输入一个字符,前端就请求一次后端接口,这无疑对后端接口带来性能压力,为了优化体验,一般都会加一个防抖机制,比如,500ms内用户没有额外的输入操作,就表示用户的输入已经稳定,才发起一次后期请求,将结果展示到页面上。

小结

本篇主要从宏观上对节流和防抖的概念进行了区分和说明,关于更多技术细节,可以参考后面的参考部分。

参考

最后编辑于: 2022-10-16

评论(0条)

(必填)
复制成功