# 节流防抖
节流:所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率
防抖:触发高频函数事件后,n秒内函数只能执行一次,如果在n秒内这个事件再次被触发的话,那么会重新计算时间。
# 节流 throttle
函数节流指的是某个函数在一定时间间隔内(例如 3 秒)只执行一次,在这 3 秒内 无视后来产生的函数调用请求
,也不会延长时间间隔。三秒后,才能进入下一个任务。
这就好比公交车,10 分钟一趟,10 分钟内有多少人在公交站等我不管,10 分钟一到我就要发车走人!
使用场景:
函数节流非常适用于函数被频繁调用的场景,例如:window.onresize() 事件、mousemove 事件、scroll 滚动事件、上传进度等情况。使用 throttle API 很简单,那应该如何实现 throttle 这个函数呢?
定时器:
function throttle(fn, interval) {
let flag = true;
return function(...args) {
if (flag){
flag = false;
setTimeout(() => {
fn.apply(this, args);
flag = true;
}, interval);
}
}
}
时间戳:
function throttle(fn, interval) {
let last = 0;
return function (...args) {
let now = +new Date();
if(now - last > interval){
last = now;
fn.apply(this, args)
}
}
}
# 防抖 debounce
防抖函数指的是某个函数在某段时间内,无论触发了多少次回调,都只执行最后一次。假如我们设置了一个等待时间 3 秒的函数,在这 3 秒内如果遇到函数调用请求就重新计时 3 秒,直至新的 3 秒内没有函数调用请求,此时执行函数,不然就以此类推重新计时。
function debounce(fn, interval) {
let timer = null;
return function (...args) {
if(timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, interval);
}
}
# 加强版 throttle
现在考虑一种情况,如果用户的操作非常频繁,不等设置的延迟时间结束就进行下次操作,会频繁的清除计时器并重新生成,所以函数 fn 一直都没办法执行,导致用户操作迟迟得不到响应。
有一种思想是将「节流」和「防抖」合二为一,变成加强版的节流函数,关键点在于「 interval 时间内,可以重新生成定时器,但只要 interval 的时间到了,必须给用户一个响应」。这种合体思路恰好可以解决上面提出的问题。
function throttle(fn, interval) {
let last = 0, timer = null;
return function (...args) {
let now = +new Date();
if(now - last < interval){
if(timer) clearTimeout(timer);
timer = setTimeout(() => {
last = now;
fn.apply(this, args);
}, interval);
} else {
// 这个时候表示时间到了,必须给响应
last = now;
fn.apply(this, args);
}
}
}