前端防抖与节流
一、防抖debounce
1.说明
防抖是指当一个事件持续触发时,在一定时间内没有再触发该事件,改事件处理函数才会执行;如果再规定时间内再次触发该事件后,时间会重新计时。
2.使用场景
在用户搜索内容时,会有一个功能:根据用户输入的内容搜索建议词;如果此时没有防抖,这样用户只要输入一个单词就会发送一次请求,这样对性能是一个严重的限制;在这种情况下,我们就用到了防抖debounce,在规定时间内用户不再输入任何信息才会执行相应的函数。
3.js实现
/**
* @desc 函数防抖
* @param func 目标函数
* @param wait 延迟执行毫秒数
* @param immediate true - 立即执行, false - 延迟执行
* 立即执行的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果
* 非立即执行版的意思是触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间
*/
function debounce(func, wait, immediate) {
let timer;
return function() {
let context = this,
args = arguments;
if (timer) clearTimeout(timer);
if (immediate) {
let callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, wait);
if (callNow) func.apply(context, args);
} else {
timer = setTimeout(() => {
func.apply
}, wait)
}
}
}
4.ts实现
export class Debounced {
/**
*
* @param fn 要执行的函数
* @param awit 时间
* @param immediate 是否在触发事件后 在时间段n开始,立即执行,否则是时间段n结束,才执行
*/
static use(fn:Function,awit:number=1000,immediate:boolean=false){
let timer:NodeJS.Timeout|null
return (...args:any)=>{
if(timer) clearInterval(timer)
if(immediate){
if(!timer) fn.apply(this,args);
timer = setTimeout(function(){//n 秒内 多次触发事件,重新计算.timeer
timer = null;//n 秒内没有触发事件 timeer 设置为null,保证了n 秒后能重新触发事件 flag = true = !timmer
},awit)
}else{
timer = setTimeout(()=>{ fn.apply(this,args)},awit)
}
}
}
}
二、节流Throttle
1.说明
节流是指当一个事件持续触发时,保证一定时间内只执行一次,即再规定时间内只执行一次
2.使用场景
当用户再进行滚动窗口或者resize页面的时候,处理函数会无限触发,会加剧浏览器性能的消耗,导致用户的体验性变差。这种情况下就可以使用节流Throttle,规定在一定时间内只执行一次。
3.js实现
/**
* @desc 函数节流
* @param func 函数
* @param wait 延迟执行毫秒数
* @param type 1 表时间戳版,2 表定时器版
* 时间戳版和定时器版的节流函数的区别就是,时间戳版的函数触发是在时间段内开始的时候,而定时器版的函数触发是在时间段内结束的时候
*/
function throttle(func, wait, type) {
if (type === 1) {
let previous = 0;
} else if (type === 2) {
let timeout;
}
return function() {
let context = this;
let args = arguments;
if (type === 1) {
let now = Date.now();
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
} else if (type === 2) {
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
}
4.ts实现
export class Throttle{
/**
*
* @param fn
* @param awit
* @param immediate true 是启用时间戳版,false 是启用定时器版,作用一样
*/
static use(fn:Function,awit:number=1000,immediate:boolean=true){
//时间戳
if(immediate){
let prevTime = 0;
return (...args:any)=>{
let nowTime = Date.now();
if(nowTime-prevTime>=awit){
fn.apply(this,args)
prevTime=nowTime
}
}
}else{
//定时器
let timer: NodeJS.Timeout|null;
return (...args:any)=>{
if(!timer){
fn.apply(this,args)
timer = setTimeout(() => {
timer&&clearTimeout(timer)
timer= null
}, awit);
}
}
}
}
}