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被挂起的情况,保证用户的正常操作效果。

原文地址:https://www.cnblogs.com/freefish12/p/5583506.html