javascript之函数节流

对于高频率的事件触发,为了优化页面性能,我们一般会对其做函数节流。比如: resize、keydow、scroll事件等。用户的频繁操作,会导致事件高频率的执行,这样会出现页面抖动啊、频繁调接口啊等问题。为了优化,我们采用函数节流,原理就是利用setTimeout控制触发回掉的频率。

1.第一种方案:

var timer;
function throttle1(fun,sec){
clearTimeout(timer);
timer = setTimeout(function(){
fun();
},sec);
} $(function(){
$(window).scroll(function(){
throttle1(function(){
console.log('我滚!!!');
},500);
});
});

第一种方案最简单,原理一看就懂,用setTimeout的目的是在用户触发之后到500毫秒之内不会执行回调,500毫秒才会执行回调一次,对于之前的事件触发是没有执行回调的。但缺陷是无法获取回调的传入参数,即使可以获取,也不能保证执行上下文this的指向。

2.第二种方案:

function throttle2(fun,sec){
var timer = null;
return function(){
clearTimeout(timer);
var context = this,arg = arguments;
timer = setTimeout(function(){
fun.apply(context,arg);
},sec);
timeer = null;
}
} $(function(){
$(window).scroll(
throttle2(function(){
console.log('我滚!!!');
},500)
);
});

第二种方案能保证回调函数的执行上下文,支持回调的多参数传入。

但是大家都知道setTimeout是一个异步函数,会被挂起,放到异步队列的最后。当主线程执行完之后,才会执行异步队列里的回调。在用户不停的操作:如不停的滚动滚动条、改变窗口大小的时候,setTimeout是会被挂起,只有在用户操作完,才会执行setTimeout的回调。那么问题来了,用户一直操作会影响正常功能使用啊!那第三种方案就是为了解决setTimeout被挂起之后,回调函数不执行的问题。

3.第三种方案:

function throttle3(fun,sec,mustRunDelay){
var timer = null;
var t_start;
return function(){
var context = this, args = arguments, t_curr = +new Date();
clearTimeout(timer);
if(!t_start){
t_start = t_curr;
}
if(t_curr - t_start >= mustRunDelay){
fun.apply(context, args);
t_start = t_curr;
}else {
timer = setTimeout(function(){
fun.apply(context, args);
}, sec);
} }
} $(function(){
$(window).scroll(
throttle3(function(){
console.log('我滚!!!');
},500,1000)
);
})

利用第三种方案,就完美的解决了setTimeout被挂起的情况,保证用户的正常操作效果。

上一篇:Java RMI之HelloWorld篇


下一篇:代码的坏味道(16)——纯稚的数据类(Data Class)