zoukankan      html  css  js  c++  java
  • #防抖和节流 #什么是防抖和节流

    一、防抖

    什么是防抖?

    有这样一种情况,想象有一个表单,点击提交按钮就发送请求给服务器。如果用户在很短的时间间隔内“手抖”点击了多次,又或者是恶意点击,那么就将发送多个请求。 该行为将造成服务器额外的不必要负载。

    所谓防抖,实际上就是是处理这种常见的情况的描述。

    实验探究

    <body>
        <button>Submit</button>
        <script>
            const btn = document.querySelector('button');
            btn.onclick = function(){
                console.log("send a request...")
            }
        </script>
    </body>
    

    该段代码,当点击Submit按钮的时候,将会触发onclick事件一次,多次点击,将多次触发。

    为了解决该问题,核心就是使用一个setTimeout 定时器。

        <body>
            <button>Submit</button>
            <script>
                const btn = document.querySelector('button');
                let timer = null;
                btn.onclick = function(){
                    clearTimeout(timer)
                    timer = setTimeout(()=>console.log("send a request..."),500)
                }
            </script>
        </body>
    

    这就是一个基本防抖的实现。如果不容易看明白,下面我们详细的分析。


    为了便于理解,我们先将第7行注释掉:

                const btn = document.querySelector('button');
                let timer = null;
                btn.onclick = function(){
                    //clearTimeout(timer)
                    timer = setTimeout(()=>console.log("send a request..."),500)
                }
    

    我们定义了一个全局变量timer用于预存setTimeout实例对象,初始值设定为null

    onclick 函数被触发一次时,函数体内timer定时器立即被触发,将在500毫秒后执行console打印。

    如果点击多次,由于setTimeout的异步执行特点,将会开启多个setTimeout 实例,各自的延时到500毫秒之后,依次执行打印。

    打印完毕后,timer被销毁。

    现在取消第7行注释:

                const btn = document.querySelector('button');
                let timer = null;
                btn.onclick = function(){
                    clearTimeout(timer)
                    timer = setTimeout(()=>console.log("send a request..."),500)
                }
    

    我们以两次间隔较短的点击为例:第一次点击时,timer为null,clearTimeout(timer)即clearTimeout(null), 这并不影响,不会报错。 然后开启了一个setTimeout定时器A,等候500毫秒后执行。 但是,如果在间隔小于500毫秒内,第二次点击,定时器A 还在等候,但是我触发onclick事件时,直接就将定时器timer,即定时器A清除了,所以定时器A内的打印就不会执行,然后开启一个新的定时器B。

    就这样,只要我在小于定时器中定义的时间间隔内重复点击,那么之前的定时器都将被清除掉。始终执行最后一个定时器。最大的外征特点就是,狂点按钮,但是只有松手的时候,最后那一次点击有效。

    以上,就是所谓的防抖,并不复杂,但是确实很巧妙。

    应用场景

    防抖的应用场景主要是为了不让一些行为频繁触发

    • keyup
    • scroll
    • resize
    • mousemove
    • 联想搜索建议
    • ...

    二、 节流

    同样是为了避免频繁触发某个行为,还有一种实现方式,它和防抖的实现有所区别。

    什么是节流?

    关于节流,我想到了一个绝佳的例子。 就是技能cd。 如果玩过无限火力小黄毛就更容易理解了。Q键恨不得不松开。

    有时候,我们希望我们能够多次触发某个行为,但是又不能让他没有间隔的疯狂触发。 那么这时候的解决方案,就叫做节流。

    我希望我在技能cd好了的时候,立即可以使用该技能。 但是总不能让你无限光速连Q吧, 那叫bug。

    实验探究

    实际上,节流的实现也很简单。

    <button>Submit</button>
    <script>
        const btn = document.querySelector('button');
        let trigger = true;
        btn.onclick = function() {
            if (trigger) {
                trigger = false;
                console.log("do something...")
                setTimeout(() => {
                    trigger = true;
                }, 1000)
            }
    
        }
    </script>
    

    简单的来讲,就是加上一个自动“开关”。

    我们预先定义了一个全局的变量trigger;当点击Submit 按钮,onclick 被触发。 然后依据trigger的值,来决定是否继续执行ifthen块中的逻辑。

    首次点击,由于trigger的预定义值为true,所以if then 块中的逻辑必定会被执行。但是一旦进入块,立即将trigger的值改作false (这样就实现了关闭了if的块逻辑执行的“开关”。),执行一次任务后,我们通过setTimeout 埋一个定时器,1秒后执行,其任务就是将“开关”再次打开。 那么第二次点击Submit按钮的时候, 如果定时器超过了一秒,“开关”被打开,即trigger为true,才会执行,if then 逻辑块中的任务。 否则就得等待“开关”被打开。

    这样,通过“开关”的控制,就能实现,即便连续点击,但是也只能按照指定的间隔时间去触发任务。 这就是节流。

    应用场景

    节流的应用场景是,依然需要让它频繁触发,但是要有规则的频繁触发。 不能让它无缝连续触发。

    • keyup
    • scroll
    • resize
    • mousemove
    • 联想搜索建议
    • ...
  • 相关阅读:
    ssh端口转发
    linux git命令安装
    linux git命令
    linux cpio命令
    linux 抓包工具
    js 深拷贝 ,浅拷贝
    vue $router 打开新窗口
    excel常用操作
    Kafka Topic的增删改查操作
    linux上删除文件名乱码的文件
  • 原文地址:https://www.cnblogs.com/jaycethanks/p/14176729.html
Copyright © 2011-2022 走看看