最简单的防抖和节流

防抖和节流很长一段时间不太懂什么意思,总觉得它们是一个东西。但是花了时间着重了解以后发现它们还是有不少区别的。

但是有个共同点就是都是使用setTimeOut定时器实现的。

1.防抖

  特点:一个函数,短时间多次触发,但是只执行最后一次触发的事件

  思路:将所有的消息推入消息队列,但是只执行最后一次的消息

  用处:如一个点击发送请求的按钮。为了防止用户由于误触导致的多次点击。所以只执行短时间内多次触发的最后一次触发。

核心代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h1>防抖:只执行最后一次的操作(频繁请求的按钮)</h1>
    <button onclick="add()">点击添加</button>
    <h3 id="num"></h3>
</body>

<script>
    let n = 1
    let h_n = document.getElementById("num")
    h_n.innerText = n
    let timer = null    // 防抖的定时器

    function add() {

        clearTimeout(timer)  // 清除上一个定时器

        timer = setTimeout(() => {
            h_n.innerText = ++n  // 数字加1
        }, 1000)

    }
</script>

</html>

说明:

  • 以一个点击数字增加的例子说明
  • 每次执行函数时都清除上一次的定时器。清除了这个定时器以后setTimeout内的代码(h_n.innerText = ++n)不再执行。
  • 如果在一秒内再次触发了add函数,那么上一次触发的定时器将不再执行

事物队列解析:

  • add()方法中的定时器数字加1的操作属于消息队列中的内容,而消息会在调用栈清空的时候执行
  • 如果在短时间(定时器的1S时间内)再次触发了add()方法,此时会先将上一个定时器清除(清除以后,上一个数字加1的操作将不再执行)
    • 对应的Event Loop的过程就是:把上一个进入消息队列的消息删除,这次新的消息将进入消息队列

 

2.节流

  特点:持续触发情况下,只会在固定的时间间隔执行。比如百度的搜索显示下拉列表的功能

  思路:只将肯定执行的消息推入消息队列

代码示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button onclick="add()">添加</button>
    <h1 id="cont"></h1>

    <script>
        let n = 1 
        let cont = document.getElementById("cont")
        cont.innerText = n
        let swch = true     // 节流的开关

        function add(){
            if(swch) {
                swch = false
                setTimeout(()=>{
                    swch = true
                    cont.innerText = ++n
                },1000)
            }
        }

    </script>
</body>

<style>
    body{
        text-align: center;
    }
</style>
</html>

 

说明:

  • add()方法内,判断一下开关是否打开,如果打开说明上一个定时器回调已经执行完毕,可以执行下一次函数。如果关闭,表示1s时间还没到,开关还没有打开,此时无法执行 ++n操作

事件队列解析:

  • 有一个全局的开关,add()方法根据这个开关决定是否将该消息推入消息队列
posted @ 2020-12-31 18:30  俄罗斯方块  阅读(136)  评论(0编辑  收藏  举报