概述
这两个函数常用于优化方面,功能分别为”将短时间内连续的操作集合成一个,也就是每段时间最多执行一次“与”将短时间内连续的操作只视作一次“。
这个说法有点抽象,可以看个图:
操作会新建时间轴,在同一个时间轴内的操作都会被”吸收”,直到时间轴结束才触发,这是节流。
每个操作都会新建时间轴,并且替换原有的,直到时间轴结束才触发,这是去抖,也可以理解成有一个公共的时间轴,每次操作都会重置他。
这里的关键就是时间轴会不会被刷新,这两个函数都是高阶函数,接受函数作为参数,同时返回新的函数,要记录下前一个操作,就得使用闭包的特性。
节流
1 | const throttle = (func, threshold = 500) => { |
首先记录上一个时间轴的初始时间 last,当与上一次执行的时间超过 500 毫秒时,表示上一个时间轴已经结束,这也就意味着本次操作会创建一个新的时间轴,所以使用 setTimeout
在 500 毫秒后触发一次,之后记录下当前时间轴的初始时间 last。
还可以换一种写法,用定时器的 ID timer 来取代时间:
1 | const throttle = (func, threshold = 500) => { |
第一次操作先使用 setTimeout
设置时间轴结束后的触发,并保存 ID 至 timer,下一次操作会判断 timer是否存在,存在表示上一个时间轴未结束,不做处理,若不存在则表示上一个时间轴已经结束,可以看作一个新操作进行处理。
去抖
与节流相比,去抖要频繁创建 setTimeout
又要频繁清除之前的 setTimeout
,所以必须保留 timer,再加上 last 这个时间变量会更加复杂,所以这里只展示 timer 的写法:
1 | const debounce = (func, threshold = 500) => { |
首先使用 timer 记录上一次的定时器 ID,有新操作时先清除定时器,再创建一个新的定时器,直到时间间隔大于 threshold,让定时器执行完成。
总结
还有更优秀的实现,比如 lodash 的,可以让 debounce 在首次操作后就立即触发,并且忽视后续操作。
这里只是用做解析的例子,所以只提供了简单的实现,这两个函数通常会用在降低操作的频繁程度上,比如百度搜索的搜索栏,使用了去抖,并不是每打一个字都会发一次搜索请求的,打字过快时就不会发请求了,直到速度暂缓或者停止时才会继续发请求。
节流也是用在类似的环境下,比如修改 viewport 尺寸会引发重排,重排多了会影响效率,这个时候可以考虑使用节流或去抖,但是去抖会在频繁操作结束后执行,而节流在频繁操作中每隔一段时间就会执行一次,这可以使操作效果更加平滑缓和。