一、概念解释
- 函数节流:是指一定时间内,js方法只跑一次。
- 函数防抖:是指频繁触发的情况下,只有空闲时间时,才执行代码一次。
二、函数节流
函数节流的关键:声明一个变量当标志位,记录当前代码是否在执行。
如果空闲,则可以正常触发方法执行。
如果代码正在执行,则取消这次方法执行,直接return
。
这个方法的作用是监听ID为
throttle
元素的滚动事件。
当canRun
为true
,则代表现在的滚动处理事件是空闲的,可以使用。
通过关卡if(!canRun)
,等于就拿到了通行证。然后下一步的操作就是立马将关卡关上canRun=false
。这样,其他请求执行滚动事件的方法,就被挡回去了。
接着用setTimeout
规定最小的时间间隔300,接着再执行setTimeout
方法体里面的内容。
最后,等setTimeout
里面的方法都执行完毕,才释放关卡canRun=true
,允许下一个访问者进来。
这个函数节流的实现形式,需要注意的是执行的间隔时间是>=300ms
。如果具体执行的方法是包含callback
的,也可以将canRun=true
这一步放到callback
中。
三、函数防抖
函数防抖的要点,也是需要一个setTimeout
来辅助实现。延迟执行需要跑的代码。
如果方法多次触发,则把上次记录的延迟执行代码用clearTimeout
清掉,重新开始。
如果计时完毕,没有方法进来访问触发,则执行代码
这个方法的作用是监听ID为
debounce
元素的滚动事件
进入滚动事件方法体的时候,做的第一件事就是清除上次未执行的setTimeout
。而setTimeout
的引用id由变量timer
记录。
clearTimeout
方法,允许传入无效的值。所以这里直接执行clearTimeout
即可。
然后,将需要执行的代码放入setTimeout
中,再返回setTimeout
引用给timer缓存。
如果倒计时300ms
以后,还没有新的方法触发滚动事件,则执行setTimeout
中的代码。
函数防抖的实现重点,就是巧用setTimeout
做缓存池,而且可以轻易地清除待执行的代码。
其实,用队列的方式也可以做到这种效果。这里就不深入了。
四、函数防抖和函数节流的使用场景
函数节流应用的实际场景,多数在监听页面元素滚动事件的时候会用到。因为滚动事件,是一个高频触发的事件。
函数防抖的应用场景,最常见的就是用户注册时候的手机号码验证和邮箱验证了。只有等用户输入完毕后,前端才需要检查格式是否正确,如果不正确,再弹出提示语
五、优化
但是,仔细想想,上面的实现方式还是有一定的缺点。如果页面很长,我们一直在滚动页面,那_log方法就一直不会被执行。所以我们可以升级一下函数防抖方法。
六、案例
每一次的用户输入都触发邮箱格式检测事件,造成了浪费,于是设置两次输入之间的时间间隔大于800ms时(用户结束输入时),再执行检查邮箱格式。
const filter= = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
$("#email").on("keyup",checkEmail());
function checkEmail(){
let timer=null;
return function (){
clearTimeout(timer);
timer=setTimeout(function(){
console.log('执行检查');
},800);
}
}