防抖(debounce)
场景
假设有一个搜索输入框,当内容变更的时候会从后台取回一些数据,并提示用户类似的数据。比如用户输入英雄
,会出现英雄联盟,英雄无敌 ...
之类的提示。
如果监听Blur
事件获取数据,那用户体验就跟没有一样。如果监听keyup, keydown
事件,请求次数过于频繁,增加了服务器的压力,并且如果服务器响应慢的话,体验也不好。那就用防抖吧。
实现防抖函数
场景中,假设用户在这1s
中没有输入新的数据,我们便向服务器发起请求。
防抖函数可以通过闭包 + 定时器实现。
function debounce(func, wait) {
let timeout = null
return function() {
clearTimeout(timeout)
timeout = setTimeout(function() {
func()
}, wait)
}
}
调用的话可以直接
function getData() {
... // ajax
}
documentElement.addEventListener('keyup', debounce(getData, 1000))
这样就很好的解决了场景1中的问题。
此时的debounce
函数并不是特别的完整。还需要解决两个问题this
, 事件对象
的问题。
- 在实际的应用场景中,大多数情况都会使用事件的第一个参数
e
获取input
的值,在闭包返回的匿名函数中拥有这个参数,但是函数是在定时器的匿名函数中执行的,所以并不具有这个参数。 - 如果不使用
debounce
函数直接绑定getData
为点击事件,在getData
中使用console.log(this)
打印出来的值是这个dom对象。所以使用了防抖函数以后也要修正这个问题。
function debounce(func, wait) {
let timeout = null
return function() {
clearTimeout(timeout)
timeout = setTimeout(() => {
func.apply(this, arguments)
}, wait)
}
}
这样就完成了一个最基本的防抖函数!