Ps: 好比搜索框,用户在输入的时候使用change
事件去调用搜索,若是用户每一次输入都去搜索的话,那得消耗多大的服务器资源,即便你的服务器资源很强大,也不带这么玩的。服务器
其中一种解决方案就是每次用户中止输入后,延迟超过500ms
时,才去搜索此时的String
,这就是防抖。app
function debounce(fn, delay) {
// 维护一个 timer,用来记录当前执行函数状态
let timer = null;
return function() {
// 经过 ‘this’ 和 ‘arguments’ 获取函数的做用域和变量
let context = this;
let args = arguments;
// 清理掉正在执行的函数,并从新执行
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(context, args);
}, delay);
}
}
let flag = 0; // 记录当前函数调用次数
// 当用户滚动时被调用的函数
function foo() {
flag++;
console.log('Number of calls: %d', flag);
}
// 在 debounce 中包装咱们的函数,过 2 秒触发一次
document.body.addEventListener('scroll', debounce(foo, 2000));
复制代码
debounce
函数封装后,返回内部函数- 每一次事件被触发,都会清除当前的
timer
而后从新设置超时并调用。这会致使每一次高频事件都会取消前一次的超时调用,致使事件处理程序不能被触发- 只有当高频事件中止,最后一次事件触发的超时调用才能在
delay
时间后执行
另外一种解决方案比 防抖 要宽松些,这时咱们不想用户一味的输入,而是给用户一些搜索提示,因此在当中限制每过500ms
就查询一次此时的String
,这就是节流。函数
function throttle(func, delay){
let prev = Date.now();
return function(){
const context = this;
const args = arguments;
const now = Date.now();
if(now - prev >= delay){
func.apply(context, args);
prev = Date.now();
}
}
}
复制代码
当高频事件触发时,第一次应该会当即执行(给事件绑定函数与真正触发事件的间隔若是大于
delay
的话),然后再怎么频繁触发事件,也都是会每delay
秒才执行一次。而当最后一次事件触发完毕后,事件也不会再被执行了。ui
2)定时器实现: 当触发事件的时候,咱们设置一个定时器,再触发事件的时候,若是定时器存在,就不执行;直到delay
秒后,定时器执行执行函数,清空定时器,这样就能够设置下个定时器。this
fucntion throttle(func, delay){
let timer = null;
return funtion(){
let context = this;
let args = arguments;
if(!timer){
timer = setTimeout(function(){
func.apply(context, args);
timer = null;
}, delay);
}
}
}
复制代码
当第一次触发事件时,确定不会当即执行函数,而是在
delay
秒后才执行。 以后接二连三触发事件,也会每delay
秒执行一次。 当最后一次中止触发后,因为定时器的delay
延迟,可能还会执行一次函数。spa
3)综合使用时间戳与定时器,完成一个事件触发时当即执行,触发完毕还能执行一次的节流函数code
function throttle(func, delay){
let timer = null;
let startTime = Date.now();
return function(){
let curTime = Date.now();
let remaining = delay - (curTime - startTime);
const context = this;
const args = arguments;
clearTimeout(timer);
if(remaining <= 0){
func.apply(context,args);
startTime = Date.now();
}else{
timer = setTimeout(func, remaining);
}
}
}
复制代码
须要在每一个
delay
时间中必定会执行一次函数,所以在节流函数内部使用开始时间、当前时间与delay
来计算remaining
,当remaining <= 0
时表示该执行函数了,若是还没到时间的话就设定在remaining
时间后再触发。固然在remaining
这段时间中若是又一次发生事件,那么会取消当前的计时器,并从新计算一个remaining
来判断当前状态。事件