zoukankan      html  css  js  c++  java
  • 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被挂起的情况,保证用户的正常操作效果。

  • 相关阅读:
    前后端项目结构规范性记录
    开发问题记录(这部分还是比较零碎)
    对HashMap的一次记录
    面试问题记录 三 (JavaWeb、JavaEE)
    面试问题记录 二 (数据库、Linux、Redis)
    面试问题记录 一 (基础部分)
    对正则表达式的一些记录
    WEB与游戏开发的一些区别
    MarkDown常用语法全纪录
    MySQL压测相关内容
  • 原文地址:https://www.cnblogs.com/freefish12/p/5583506.html
Copyright © 2011-2022 走看看