为什么要使用防抖与节流?
- 举一个栗子八:
html:
无节流与防抖 <input type="text" name="" id="normal">
js:
window.onload=function(){
// 模拟ajax请求
function ajax(content){
console.log('ajax request'+content);
}
let iptnormal=document.getElementById('normal');
iptnormal.addEventListener('keyup',e=>{
ajax(e.target.value)
})
}
- 结果
从运行截图可以看出,每次输入一个数字,就会发送一次ajax请求。
在实际应用中,处理函数在短时间内被频繁调用,如果处理函数还需要调用后台接口,那么可能上次还没有响应,下一次请求又来了。这样无意中增加了服务器的压力,而且对用户来说,也会造成卡顿。
防抖
什么是防抖?
在事件被触发n秒后,再执行回调函数,如果在这n秒内事件又被触发,则重新计算时间。
- 举一个栗子八:
html:
防抖后的输入:
<input type="text" name="debounce" id="debounce">
js:
window.onload = function () {
//模拟ajax请求
function ajax(content) {
console.log('ajax request ' + content)
}
// 防抖
function debounce(fun, delay) {
return function (args) {
// 保存传入参数(e.traget.value)
let _args = args
//每次事件被触发,都会清除当前的timer,然后重写设置超时调用
clearTimeout(fun.id)
fun.id = setTimeout(()=> {
fun.call(this, _args) // 调用ajax函数
}, delay)
}
}
let inputDebounce = document.getElementById('debounce')
let debounceAjax = debounce(ajax, 500)
inputDebounce.addEventListener('keyup', function (e) {
debounceAjax(e.target.value)
})
}
- 结果:
- 说明:
1.每一次事件被触发,都会清除当前的 timer 然后重新设置超时调用,即重新计时。 这就会导致每一次高频事件都会取消前一次的超时调用,导致事件处理程序不能被触发;
2.只有当高频事件停止,最后一次事件触发的超时调用才能在delay时间后执行;
简单实现
function debounce(event,time){
let timer=null;
return function(...args){
clearTimeout(timer);
timer=setTimeout(()=>{
event.apply(this,args);
},time);
};
}
应用场景
- 短信验证码
- 提交表单
- resize 事件
- input 事件(当然也可以用节流,实现实时关键字查找)
节流
什么是节流?
规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。
- 举个栗子八
html:
3.加入节流后的输入:
<input type="text" name="throttle" id="throttle">
js:
window.onload = function () {
//模拟ajax请求
function ajax(content) {
console.log('ajax request ' + content)
}
// 节流
function throttle(fun, delay) {
let last, deferTimer
return function (args) {
// 保存实参
let _args = arguments;
let now = +new Date();
if (last && now < last + delay) {
clearTimeout(deferTimer);
deferTimer = setTimeout(()=> {
last = now;
fun.apply(this, _args);
}, delay)
} else {
last = now;
fun.apply(this, _args);
}
}
}
let throttleAjax = throttle(ajax, 1000)
let inputThrottle = document.getElementById('throttle')
inputThrottle.addEventListener('keyup', function (e) {
throttleAjax(e.target.value)
})
}
- 结果
- 说明 通过结果可以看出,每1秒执行一次ajax请求
简单实现
时间戳实现
第一次事件一定触发,最后一次一定不触发
function throttle(event,time){
let pre=0;
return function(...args){
if(Date.now()-pre>time){
pre=Date.now();
event.apply(this,args);
}
}
}
定时器实现
第一次事件不会触发,最后一次一定触发
function throttle=function(event,time){
let timer=null;
return function(...args){
if(!timer){
timer=setTimeout(()=>{
timer=null;
event.apply(this,args);
},time);
}
}
}
结合版
时间戳和定时器的结合版,也相当于节流和防抖的结合版,第一次和最后一次都会触发
function throttle(event,time){
let pre=0;
let timer=null;
return function(...args){
if(Date.now()-pre>time){
clearTimeout(timer);
timer=null;
pre=Date.now();
}else {
timer=setTimeout(()=>{
event.apply(this,args);
},time);
}
}
}
应用场景
- scroll 事件,单位时间后计算一次滚动位置
- input 事件(上面提到过)
- 播放事件,计算进度条
最后:本文章仅仅是本人学习的笔记,文章中的参考文献,若原博主介意,请联系我,马上删除
参考文献:juejin.cn/post/684490…