防抖与节流

139 阅读3分钟

js复习笔记——防抖节流

防抖

防抖(debounce)顾名思义防止抖动嘛,我的理解是程序防止应用户的误触而进行频繁操作,也可用于对高频触发事件进行约束(既然用户还要进行频繁操作,我为什么不等用户操作完,程序再进行响应呢,这时候就需要一个程序等待时间了,用户在进行了一次操作后,程序计时)。用户在等待时间内没有再进行操作,程序默认为是用户已经肯定自己想进行的操作已经做完了,这时候程序就可以响应了,如果用户在等待时间内发现自己有错误操作,可以及时进行修改,而程序不做反应。这个等待时间如果太短了,那对程序的优化会显得不足,时间太长了会影响用户体验,所以这个等待时间要考虑好。

简单的举个防抖的例子,就是那个最经典的输入框输入的例子吧

要求:一个输入框进行实时查询,用户每输入一个字符,程序进行查询操作,如果用户要输入一万次(夸张了),那我们也要查询一万次。所以我们进行优化,当用户在进行一次输入后2s没再输入了,就进行验证。

没进行优化:

<input type="text" placeholder="请输入..." id="input1">
    <script>
        const input1 = document.getElementById("input1")
        input1.addEventListener("input",(event)=>{
            console.log("进行验证",event.target.value)
        })
    </script>

image-20220411204238927.png

你输入多少次,程序就验证多少次

优化后:

input1.addEventListener("input", (event) => {
            debounce(() => {
                console.log("进行验证", event.target.value)
            }, 2000)
        }
​
        )
        //进行简单的防抖封装
        let timer = null
        function debounce(fn, awaitTime) {
            if (timer) {
                clearTimeout(timer)
            }
            timer = setTimeout(fn, awaitTime)
        }

使用闭包:

input1.addEventListener("input",
            debounce((event) => {
                console.log("进行验证",event.target.value)
            }, 2000)
        )
        function debounce(fn, awaitTime) {
            let timer = null
            return (...args) => {
                if (timer) {
                    clearTimeout(timer)
                }
                timer = setTimeout(()=>fn.apply(this,args), awaitTime)
            }
        }

image-20220411204348146.png

节流

节流(throttle),我的理解是,本来可以2s进行20次操作,但我做出限制,2s内只能进行1次操作,这不就相当于减少“流量”了嘛(就像一个水龙头全打开,水哗啦哗啦的流,但我把开关拧紧,让他一次只留出一滴水一样)。就是一定时间只调用一次函数

举个例子:监听鼠标移动事件

要求:每2s中触发一次

没优化之前:

box1.addEventListener("mousemove",(event)=>{
            console.log("("+event.screenX+","+event.screenY+")")
            span.innerHTML = "("+event.screenX+","+event.screenY+")"
        })

image-20220411210039472.png

优化之后:

 box1.addEventListener("mousemove", throttle((event) => {
            console.log("(" + event.screenX + "," + event.screenY + ")")
            span.innerHTML = "(" + event.screenX + "," + event.screenY + ")"
        }, 2000))
        //进行简单的节流封装
        function throttle(fn, time) {
            //上一个时间戳
            let preTime = 0
            return (...args) => {
                //现在的时间戳
                let nowTime = Date.now()
                let timeSwap = nowTime - preTime
                if (timeSwap > time) {
                    fn.apply(this, args)
                    preTime = nowTime
                }
            }
        }

image-20220411212028016.png

感觉还是不太清楚啊,还是用防抖那个例子吧

image-20220411212234276.png

如果我一直输入,节流每个2s验证一次,而防抖是只在最后一次生效

补充关于clearInterval(timer)与timer = null

image-20220412081622060.png

但打印timer,是TimeOut对象

image-20220412091311297.png

如果将timer赋null,并不能停止定时器 timer就像定时器的唯一标识符,你能通过它找到该定时器,从而利用clearInterval将该定时器消除。

总结

总之,我认为防抖和节流都是可以对高频操作进行约束的很好的策略。

在学习防抖和节流过程中,我一开始的感觉他们也很容易区分,到好像又把他们混淆了,再到最后好像懂了,在这个过程中我看了很多关于防抖和节流的资料,对笔记改了很多次,如果还是存在错误,请指出,谢谢大家浏览,希望能对你我产生帮助。