- 节流防抖 是什么
- 应用场景区分
- 实现
参考
https://zhuanlan.zhihu.com/p/38313717
https://juejin.im/post/5b8de829f265da43623c4261
节流和防抖#
处理频繁请求的业务场景,比如「输入框keyup实时搜索查询请求」 「页面滚动触发的事件」,不处理的话 可能会频繁请求给服务器带去太大压力吧,滚动或者浏览器缩放这样的会带来前端性能问题。
所以我们可以控制在一定时间内的请求次数,节流防抖都是干这个事情,应用场景有点差别
设置/清除最小时间段的定时器setTimeout/clearTimeout
场景1:实时搜索,input-keyup每次输入后触发keyup事件去发请求
我们可以设置一个定时间延迟一段时间(delay:1000)比如1s后去执行这个请求,如果用户在1s内又输入触发了该事件则清除该定时器,重新设置。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| // 模拟请求
function ajax(content) {
console.log('ajax request---', new Date().toLocaleTimeString(), content)
}
function debounce(func, delay) {
let timer
return function(args) {
clearTimeout(timer)
setTimeout(() => {
func.call(this, args)
}, delay)
}
}
const debounceAjax = debounce(ajax, 1000) // 防抖函数
input.addEventListener('keyup', function(e) {
debounceAjax(e.target.value)
})
|
场景2:相对于上述keydown/keyup来说 resize/drag事件触发的频率会更加高(不间断),所以如果还用上述防抖函数来写的话,可能很难触绑定事件。比如上述delay=1s,要是每隔0.5s去触发一次事件的话,那么要执行的请求则永远在setTimeout不会执行,所以这个时候。我们需要做的是,在上述基础上加上一个「至少执行一次的时间间隔」,这个就需要比较两次请求的时间差来判断是否要执行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| function throttle(func, delay) {
let last, deferTimer
return function(args) {
console.log('23232')
let now = +new Date()
if(last && now < last + delay) {
clearTimeout(deferTimer)
deferTimer = setTimeout(() => {
last = now
func.call(this, args)
}, delay);
}else {
last = now
func.call(this, args)
}
}
}
const throttleAjax = throttle(ajax, 1000)
input.addEventListener('keyup', function(e) {
debounceAjax(e.target.value)
})
|
总之,防抖和节流都是为了减少一段时间内的频繁请求/操作次数,减少服务端处理请求压力或者客户端渲染压力。节流相比于防抖而言,处理更加频繁的事件操作比如鼠标滚动 浏览器缩放等等连续过程的事件,防抖的话比较适合实时输入搜索请求吧。