js中连续触发事件的稀释方法(函数节流、函数防抖、标识变量)

在浏览器中操作DOM比非DOM交互需要更多的内存和CPU的事件,连续尝试进行过多的DOM相关操作可能UI导致浏览器挂起,有时甚至会崩溃。尤其在IE中使用onresize事件处理程序的时候容易发生,当调整浏览器大小的时候,该事件会连续触发。在onresize事件处理程序内部如果尝试进行DOM操作,其高频率的更改可能会让浏览器崩溃。为了解决短时间内重复调用事件的这个问题,可以使用函数节流、函数防抖和设置标识变量的方法

函数节流

函数节流背后的思想是指某些代码不可以在没有间断的情况下连续重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码。当第二次调用该函数时,它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行过了,这个操作就没有任何意义。然而,如果前一个定时器尚未执行,其实就是将其替换为一个新的定时器。目的是只有在执行函数的请求停止了一段时间之后才执行。实现函数的基本模式如下

var processor = {
    timeoutId: null,
    performProcessing:function(){
        //实际执行的代码
        console.log('eee');
    },
    percess: function(){
        clearTimeout(this.timeoutId);

        var that = this;
        this.timeoutId = setTimeout(function(){
            that.performProcessing();
        },200)
    }

}

该函数的主要意思是,当在200ms以内再次触发performProcessing事件时,就删除触发该事件的定时器并重新新建一个触发该事件的定时器。当最后一次调用process之后至少200ms后才会调用performProcessing()。 该模式的简化形式如下

 function throttle(method,context){
    clearTimeout(method.tId);
    method.tId = setTimeout(function(){
        method.call(context);
    },200);
}

该函数接收两个参数:要执行的函数以及在哪个作用域中执行。首先清除之前设置的任何定时器。定时器ID是存储咋函数的tId属性中的,第一次吧方法传递给torottle()的时候,该属性并不存在。接下来创建定时器,并将ID存储在方法的tID属性中。如果这是第一次对这个方法调用throttle()的话,那么这段代码会创建该属性。定时器会使用call()来确定方法在适当的环境中执行。如果没有给出第二个参数,那么就在全局作用域中执行
我们使用上述简化方法实现resize事件的节流。下面函数主要实现当改变窗口尺寸的时候

function resizeDiv(){
    var div = document.getElementById('myDiv');
    div.style.height = div.offsetWidth + 'px';
}

window.onresize = function(){
    throttle(resizeDiv);
}

函数防抖

如果一直触发一个事件,函数节流的方法定义的方法永远不会执行,就像一个水龙头,如果关闭了,永远不会出水;函数防抖的方法像一个关闭水龙头不好用,当关闭水龙头隔一段时间会有滴水一样。就是一个事件如果频繁触发,会隔一段时间执行一次。
函数防抖的实现方式如下

var debounce  = function(fn,delay,mustRunDelay){
    var timer = null;
    var t_start;
    return function(){
        var context = this;
        var args = arguments;
        var t_curr = +new Date();
        clearTimeout(timer);
        if(!t_start){
            t_start = t_curr;
        }
        if(t_curr - t_start >= mustRunDelay) {
            fn.apply(context,args);
            t_start = t_curr
        } else {
            timer = setTimeout(function(){
                fn.apply(context,args);
            },delay);
        }
    } 
}

该函数接收三个参数,分别为要执行的函数,隔多长时间清除函数定时器以及多长时间需要执行一次。
如果利用函数防抖实现resize事件,实现方法如下

window.onresize = throttleV2(resizeDiv,50,100);

标识变量法

在项目中需要使用scroll事件,当scroll滚动到页面底部时,发送请求验证还有没有其他的资源需要加载。如果直接使用scroll事件,当滚动到文档底部发送ajax请求的话,ajax请求会连续触发。为了解决这个问题,设置一个初始值为true的标志变量,只有标识变量为true时才能发送ajax请求。当发送ajax请求时,将标志变量设为false,收到请求的响应并处理完后将标志变量设为true。整个代码如下

var pageIndex = {
    newPage : 1,
    hotPage:1
}
var scrollFlag = {
    newFlag: true,
    hotFlag: true,
}
EventUtil.addHandler(window,'scroll',function(){
            scrollE(newPost,'new');
        })

function scrollE(ele,str){
var totalHeight = document.documentElement.scrollTop + document.body.scrollTop + document.documentElement.clientHeight ;

    if(totalHeight > ele.offsetTop + ele.offsetHeight) {
        if(scrollFlag[str + "Flag"]){
            scrollFlag[str + "Flag"] = false ;
            if(pageIndex[str + "Page"]< 10) {
                pageIndex[str + "Page"]++;

                var xhr=createXHR();
                var postHtml = ele.innerHTML;
                xhr.onreadystatechange=function(){

                    if(xhr.readyState==1){
                        ele.innerHTML = postHtml + '<div class = "loading"><div class="load-info"><span class="load-img"></span>我去拿数据 等我一会儿</div></div>'
                    }
                    if (xhr.readyState == 4) {
                        if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
                            var res = xhr.responseText;
                            res = JSON.parse(res);

                            ele.innerHTML = postHtml + res.htmlres;

                            if(res[str+'IsLastPage']){
                                ele.innerHTML = ele.innerHTML+'<div class = "final-page"><span>别拉啦 我已经加载完了<span></div>'
                            } else {
                                scrollFlag[str + "Flag"] = true;
                            }

                        }else{

                            console.log("request was unsuccessful:"+xhr.status);
                        }
                    }
                }
                xhr.open('GET','postpage/' + str + '/' + pageIndex[str + "Page"],true);
                xhr.send(); 
            }   
        }           
    }       
} 
函数节流函数防抖都是为了减少目标函数的频繁执行,特别是那些计算量较大、耗费性能较多的函数函数节流适用于大量事件按照时间均匀触发的情况,而函数防抖适用于多次事件只需要响应一次的情况。 函数节流的实现方式主要是通过设置一个定时器,在指定的时间间隔内只执行一次目标函数。当事件触发时,如果定时器已经存在,则不执行目标函数,并重新开始计时,直到定时器到期后执行目标函数。这样可以将大量事件按照时间均匀分配触发,减少频繁执行目标函数的情况。 而函数防抖的实现方式是设置一个定时器,在指定的时间间隔内只执行一次目标函数。当事件触发时,如果定时器已经存在,则清除定时器并重新开始计时,直到定时器到期后执行目标函数。这样可以避免多次事件触发时频繁执行目标函数,只在最后一次事件触发后执行目标函数。 在JavaScript函数节流函数防抖可以通过编写相应的函数来实现。函数节流可以通过设置一个定时器,在指定的时间间隔内执行目标函数函数防抖可以通过设置一个定时器,在指定的时间间隔内只执行一次目标函数。 总结来说,函数节流函数防抖是为了减少频繁执行目标函数而设计的技术,在不同的场景选择合适的方式可以提升性能和用户体验。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [js函数节流js函数防抖](https://blog.csdn.net/MFWSCQ/article/details/100130519)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [js函数防抖函数节流](https://blog.csdn.net/m0_52900946/article/details/124778757)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值