1.什么是函数防抖?
官方的解释:当调用动作过n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间。
看完难免有点懵逼,所以我自己的路理解就是。
公交车停站后,为了更好的接待游人。在最后一个人上车后原地等待20s钟,在等待20s的时候有人赶来了,等他上车后再等待20s钟,假如在20s内又等来一个人就继续等待20s。相当于刷新了等待20s这个机制。
再通俗的一个例子就是,派克的R,在斩杀英雄之后可以在20s内连续斩杀英雄,假如在这20s又斩杀了一个英雄就继续刷新,在20s内又可以斩杀一个英雄…(这个例子是真的好明白)
2.实战中碰到问题
举个例子,当我们一个项目里面要加载30张图片,这时候我们在所有图片都加载完成后执行某项操作。
我们可以利用img标签的onload时间来监听每一张图片是否加载完成。
但是因为我们加载了30张图片,就需要执行refresh函数30次,大大的降低了程序的性能,也会让浏览器卡顿,降低了用户的使用体验。
所以我们需要使用函数防抖来解决这个问题。
3.函数防抖的模拟实现
//函数防抖的实现
{
//模拟向服务器请求数据refresh函数
function refresh() {
console.log("数据加载");
}
/**
* 封装防抖函数
*/
function debounce(func, delay) {
let timer = null;
return function (...args) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
func.apply(this, args)
}, delay)
}
}
let testRefresh = debounce(refresh, 600);
//模拟向服务器请求30次refresh函数
let count = 0;
let timer = setInterval(() => {
count++;
testRefresh();
if (count > 9) {
clearInterval(timer);
}
}, 500)
}
- 执行第1次. timer 为null,直接执行下面的回调函数setTimeout ,setTimeout函数不会立即执行,有一个delay暂停
时间500ms, - 执行第2次. 在1暂停的过程中 2进行 timer 有值所以清空之前的值,然后继续执行回调函数setTimeout,又一次碰到delay 暂停时间500s,
- 执行第3次 在2暂停的过程中 3进行 timer 有值所以清空之前的值,然后继续执行回调函数setTimeout,又一次碰到delay
暂停时间500s,
…
…
… - 执行第10次. timer有值 但是没有第11次,所以等待500m后没有下次函数调用了,这时候拿到func函数,传入那个函数将this绑定到这个函数上且将传入的参数传给这个传入的函数。
————————————————————————————————
注意事项:
可以看到我封装的防抖函数传入每次等待时间为600ms,而模拟从服务器请求一次数据的时间为500ms,这样就可以保证第一次请求完后,等待600m的时间内,发起来第二次服务器请求,这样就取消了timer。
————————————————————————————————