js 中的截流函数throttle 和 debounce

JavaScript017

js 中的截流函数throttle 和 debounce,第1张

以前处理过高频事件,但是没有好好总结弄一下,这回抽点时间说一下。5

做过动画效果的同学一定经常碰到滚动控制的问题,像滚动或者resize这样的事件,触发频率太高又没啥规律可循,这个时候就有两个截流函数给我们使用:throttle和debounce。

throttle是让一个函数在指定的时间执行一次。比如用户滚动1s,只触发一次scroll事件。

debounce是让一个函数延迟一定的时间然后执行,只要触发这个函数,就重新开始等,到时间了然后执行。有网友给出了形象的电梯比喻这里我贴出来。

电梯比喻---debounce:(你在进入电梯后发现这时不远处走来了了一个人,等10秒钟,这个人进电梯后不远处又有个妹纸姗姗来迟,怎么办,再等10秒,于是妹纸上电梯时又来了一对好基友...,作为感动中国好码农,你要每进一个人就等10秒,直到没有人进来,10秒超时,电梯开动)

下面开动 自己实现一下。(注:在lodash underscore 中都实现了截流函数)

现在讲一下大概的思路,首先函数进来需要延迟执行,在延迟执行结束之前都不可以再次执行,所以我们用wait 作为一个flag作为判断,在fn执行完毕之后讲wait 设定回初始值(也就是允许函数再次执行)。

debounce 函数

debounce 的思路类似,每一次触发函数,都要去清除上一次的timer,甚至连wait  都可以省了。是不是很简单。

这个只是简易的实现,lodash弄的比较复杂,但是基本的原理都是一样的。

在我们日常的开发中,以下几种情况会高频率的触发事件:

高频率的触发事件,会过度损耗页面性能,导致页面卡顿,页面抖动,尤其是当这些事件回调函数中包含ajax等异步操作的时候,多次触发会导致返回的内容结果顺序不一致,而导致得到的结果非最后一次触发事件对应的结果。

Debounce:一部电梯停在某一个楼层,当有一个人进来后,20秒后自动关门,这20秒的等待期间,又一个人按了电梯进来,这20秒又重新计算,直到电梯关门那一刻才算是响应了事件。

Throttle:好比一台自动的饮料机,按拿铁按钮,在出饮料的过程中,不管按多少这个按钮,都不会连续出饮料,中间按钮的响应会被忽略,必须要等这一杯的容量全部出完之后,再按拿铁按钮才会出下一杯。

这里我们使用 Lodash 库里面实现的debouce和throttle方法。

lodash支持自定义封装,使用下面两个命令封装一个我们自己的lodash库。

debounce调用方法: _.debounce(func, [wait=0], [options={}]) 返回一个具有debounce策略的新函数。

throttle调用方法: _.throttle(func, [wait=0], [options={}]) 返回一个具有throttle策略的新函数。

下面的例子是在移动端使用 rem 布局常用的一个函数,侦听 resize 事件改变根元素的 fontSize ,这种情况下适用debounce策略:

这个例子中,使用 throttle 策略,点击一次生成一行文字,1s中无论怎么点击,都只生成一行文字:

完整demo地址: demo

debounce.js

throttle.js