节流防抖

91 阅读2分钟

为什么需要节流和防抖

一些浏览器事件,比如window.onresize、window.mousemove等触发频率很高,会造成页面卡顿。如果在这些事件里面向后台发送请求,会对服务器造成不必要的压力。

那么限制事件处理函数频繁调用的方法就是节流throttle和防抖debounce

函数节流(throttle)

概念:当函数执行完一次之后,只有大于设定的执行周期才会执行第二次,适合多次事件按时间做平均触发。(两次操作间隔一个已经确定的周期,第二次操作就会被执行)通俗来讲可以把事件的频繁发生看成一个水流,原来的流速是100次/s,节流之后可以实现10次/s。

场景:

窗口调整(resize)、页面滚动(scroll)、DOM元素的拖拽(mousemove)、抢购疯狂点击(click)

手写实现(在wait内最多执行一次callback)

     window.addEventListener('scroll',throttle(function(e){
            console.log(e)},500)
        );
        function throttle(callback,wait){
            //定义开始时间
            let start = 0;

            //返回一个函数
            return function(...args){
                //获取当前时间戳
                let now = Date.now();
                if(now - start >= wait){//如果大于执行周期
                    //this指向当时的事件源
                    callback.apply(this,args);
                    start = now;
                }

            }
        }

防抖debounce

概念:两次操作间隔时间小于我们设定的定时器的时间就不执行。(短时间内多次触发事件,只执行最后一次)

场景:表单输入验证、表单输入触发搜索 ajax、resize/scroll/touch/mouseove 事件

          let input = document.querySelector('input');
        input.oninput = debounce((e) =>{
            console.log(e.target.value);
        },500)
        
        function debounce(callback,time){
            //定时器变量
            let timeId = null;
            //返回一个函数
            return function(...args){
                //当有一个定时器在跑的时候
                if(timeId != null){
                    //清空定时器
                    clearTimeout(timeId);
                }

                //启动定时器 返回一个数字
                timeId = setTimeout(()=>{
                    callback.apply(this,args);
                    //重置定时器变量
                    timeId = null;
                },time)
                
            }
            
        }