防抖和节流就是对用户请求频率做限制,使其在一定时间内只能执行一次,以减少服务器压力。
防抖
在事件被触发n秒内函数只会执行一次,若n秒内再次触发事件则重新计时。
//防抖:在事件被触发n秒内函数只会执行一次,若n秒内再次触发事件则重新计时。
<input type="text" class='debounce'>
//防抖
function debounce(fn, delay, boolean) {
var timer = null;//不是私有的,公用的
return function() {
clearTimeout(timer);
if (boolean) { //立即执行
if (!timer) {
//timer值为null,说明是第一次或者距上一次执行已经过了delay时间
fn.apply(this, arguments);
//this:input标签 arguments[0]:event事件对象
//timer = setTimeout(() => {
//不能写到这里来,假如在1s内连续触发多次,由于上面设置了的clearTimeout加
//上这里的if判断,会导致这里的 timer=null 无法被执行,即fn得不到执行,防抖
//失效
// timer = null;
// console.log(22)
//}, delay)
}
timer = setTimeout(() => {
timer = null;
}, delay)
} else { //非立即执行(延迟之后才会执行)
timer = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
}
}
}
// 处理函数
function handle() {
console.log(Math.random());
}
document.querySelector('.debounce').oninput = debounce(handle, 1000, true);
节流(throttle)
防抖有个缺点,比如用户一直点击,那么事件就一直触发,计时无线后延,回调函数就一直得不到执行。但当我们需要点击事件n秒内就必须执行回调,此时就需要节流。防抖是以最后一次触发事件为计时初始,而节流是以第一次触发事件为计时开始的。也就是说,使用防抖时当用户在给定时间间隔内连续触发事件前面的都不执行回调(被清除定时器了),只有最后一次执行;而节流是第一次触发事件开始计时,计时结束执行回调,计时期间触发的不执行回调。
函数节流主要有两种实现方法:时间戳和定时器。
<input type="text" class='debounce'>
document.querySelector('.debounce').oninput = throttle(handle, 1000);
function handle() {
console.log(Math.random());
//为什么会立刻输出不用等待1s,因为 throttle(handle, 1000) 在输入数据之
//前就执行了,即 lastTime 早就有值了
}
//时间戳:会立即执行一次事件(因为第一次nowTime-lastTime肯定大于delay)
function throttle(fn, delay){
let lastTime = 0;//不是私有的,公有的
return function(){
let nowTime = Date.now();//静态方法,相当于new Date().getTime()
if(nowTime-lastTime>delay){
fn.apply(this,arguments);
lastTime = nowTime;
}
}
}
//定时器:延迟之后才会执行一次事件
function throttle(fn, delay) {
let timer = null;//不是私有的,公用的
return function(){
if(!timer){
timer = setTimeout(()=>{
fn.apply(this,arguments);
timer = null;//只有上一次调用执行完毕,才设置timer=null
},delay)
}
}
}
总结
区别: 函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。 比如我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据,这样的场景,就适合用节流技术来实现。