在JavaScript中,当一个事件被频繁触发,并且处理函数比较耗资源时,往往容易造成性能问题和影响用户体验。
例如,当用户缩放或滚动页面时执行大量的计算,将可能导致页面卡顿,甚至页面异常退出。
这时就需要限流,即限制处理函数的执行频率。
/**
* 限流函数: 连续调用时,限制函数单位时间内只被执行一次。
* @param { function } fn
* @param { number } interval 时间间隔(ms)
/
function throttle(fn, interval){
if('number' != typeof interval && !(interval instanceof Number)){
throw new TypeError('第二个参数是时间间隔(ms),请输入整数);
return;
}
let lastTime = 0;
return wrapper(){
let pastTime = Date.now() - lastTime;
let self = this;
let args = arguments;
function exec(){
lastTime = Date.now();
fn.apply(self, args);
}
if(pastTime > interval){
exec();
}
}
}
频繁地触发事件,除了可能产生性能问题,还容易导致重复执行或不必要的处理。
例如,用户频繁地点击按钮,容易导致重复提交请求。
另外,用户在输入框连续输入时,频繁地触发请求,实际只有最后一次请求才是有效的。
这时就需要防抖,即限制函数只被执行一次。
/**
* 防抖函数: 连续调用时,限制函数只被执行一次。
* @param { function } fn
* @param { number } interval 时间间隔(ms)
* @param { boolean } atBegin 是否第一次执行
/
function debounce(fn, interval, atBegin=true){
if('number' != typeof interval && !(interval instanceof Number)){
throw new TypeError('第二个参数是时间间隔(ms),请输入整数);
return;
}
let timeoutID = undefined;
return wrapper(){
let self = this;
let args = arguments;
function exec(){
fn.apply(self, args);
}
function clear(){
timeoutID = undefined;
}
if(atBegin && !timeoutID){
exec();
}
if(timeoutID){
clearTimeout(timeoutID);
}
timeoutID = setTimeout(atBegin ? clear() : exec(), interval);
}
}
限流和防抖都是用来处理频繁事件的。频繁地触发事件,容易产生性能问题,这时就需要限流,即限制函数执行频率。另外,还可能导致重复执行和不必要的处理,这种需要防抖,即限制函数只执行一次。