/*
* 防抖
* 思路:根据定时器的创建与销毁来判断是否进行fn操作
* 操作结束后一段时间wait秒内,没有再次触发该操作,fn才执行
* 如果wait秒内又触发了该操作,则重新计时,重新等待wait秒后执行
* 若需要先立即执行一次,在定时器生效前定一个flag
* 业务场景:搜索联想、防止重复抽奖/支付等
*/
function debounce(fn,wait,rightnow){
let timer = null;
return function () {
let that = this;
let args = arguments;
timer && clearTimeout(timer);
if(rightnow){
let flag = timer;//立即执行
}
timer = setTimeout(()=>{
fn.apply(that,args);
},wait)
if(rightnow && !flag){//立即执行版本
fn.apply(that,args)
}
}
}
let fn = function(){
console.log(document.body.scrollTop ||document.documentElement.scrollTop)
}
window.onscroll = debounce(fn,1000);
/*
* 节流
* 思路: 根据当前时间间隔来判断是否执行fn
* 对于连续触发的事件,在一定的时间wait秒内,函数fn只执行一次
* 业务场景:上拉刷新、图片懒加载等
* */
function throttle(fn,wait) {
let start = 0;
return function loop(){
let now = Date.now();
let flag = now - start - wait,//触发条件 是否达到要求的时间间隔
that = this,
args = arguments;
if(flag >= 0){
fn.apply(that,args);
start = now;
}
}
}
let fn = function(){
console.log("scrollTop",document.body.scrollTop||document.documentElement.scrollTop)
}
window.onscroll = throttle(fn,1000);
这两者的区别在于:
防抖需要在特定的操作结束后或者结束时才会执行(设置的间歇时间wait)次,而节流函数会让会执行(实际操作持续的时间time/设定的间歇时间wait)次,比如搜索联想需要在输入完全结束后才执行联想功能,才可以减少请求次数,具有多次抽奖机会时,需要等到第一次抽奖结果返回并执行todos后,才能进行第二次抽奖,这种类型的业务场景我们就选择防抖函数,而另外,当我们在另一些业务场景时,比如上拉刷新,多次触发时,当然不需要不断请求,也不是只能请求一次,我们需要让他每隔几秒请求一次,达到减少请求次数的要求,又能让用户对自己多次操作又一定的交互体验。