节流
节流的原理很简单:
如果你持续触发事件,每隔一段时间,只执行一次事件。
根据首次是否执行以及结束后是否执行,效果有所不同,实现的方式也有所不同。
我们用 leading 代表首次是否执行,trailing 代表结束后是否再执行一次。
关于节流的实现,有两种主流的实现方式,一种是使用时间戳,一种是设置定时器。
使用时间戳
让我们来看第一种方法:使用时间戳,当触发事件的时候,我们取出当前的时间戳,然后减去之前的时间戳(最一开始值设为 0 ),如果大于设置的时间周期,就执行函数,然后更新时间戳为当前的时间戳,如果小于,就不执行。
看了这个表述,是不是感觉已经可以写出代码了…… 让我们来写第一版的代码:
第一版
1 | function throttle(func, wait) { |
例子依然是用讲 debounce 中的例子,如果你要使用:1
container.onmousemove = throttle(getUserAction, 1000);
效果演示如下:
使用时间戳
我们可以看到:当鼠标移入的时候,事件立刻执行,每过 1s 会执行一次,如果在 4.2s 停止触发,以后不会再执行事件。
使用定时器
接下来,我们讲讲第二种实现方式,使用定时器。
当触发事件的时候,我们设置一个定时器,再触发事件的时候,如果定时器存在,就不执行,直到定时器执行,然后执行函数,清空定时器,这样就可以设置下个定时器。
第二版
1 | function throttle(func, wait) { |
为了让效果更加明显,我们设置 wait 的时间为 3s,效果演示如下:
使用定时器
我们可以看到:当鼠标移入的时候,事件不会立刻执行,晃了 3s 后终于执行了一次,此后每 3s 执行一次,当数字显示为 3 的时候,立刻移出鼠标,相当于大约 9.2s 的时候停止触发,但是依然会在第 12s 的时候执行一次事件。
所以比较两个方法:
第一种事件会立刻执行,第二种事件会在 n 秒后第一次执行
第一种事件停止触发后没有办法再执行事件,第二种事件停止触发后依然会再执行一次事件