来聊聊JavaScript中的防抖和节流

Posted liujunhang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了来聊聊JavaScript中的防抖和节流相关的知识,希望对你有一定的参考价值。

javascript防抖和节流

问题还原

我们先来通过代码把常见的问题还原:

<html>
<head>
    <meta charset="utf-8">
    <title>问题演示</title>
</head>
<body>


    <script type="text/javascript">
        window.onload = function()
            // 没有处理防抖和节流的代码
            let norInput = document.getElementById('normal');
            
            let ajax = content=>
                console.log('ajax:' + content);
            

            norInput.addEventListener('keyup',e=>
                ajax(e.target.value)
            )
            // console.log(debounce()())
        
    </script>

    <input type="text" name="normal" id="normal">

</body>
</html>

在上面的程序中,看上去是没有什么问题,但是用户每输入一个字符,都会向后端发起一次请求,而这只是一个用户,如果同时很多用户进行相同的操作,无异于是给服务端造成极大的压力。

而解决这种问题,有很多种合适的方法,但是下文要说到的,是关于JavaScript当中的防抖节流操作。

防抖

什么是防抖

当用户在触发一次事件n秒后在执行回调函数,如果重复触发则进行重新计时。

根据防抖的逻辑,下面通过代码来进行模拟:

<html>
<head>
    <meta charset="utf-8">
    <title>问题演示</title>
</head>
<body>


    <script type="text/javascript">
        window.onload = function()
            
            let norInput = document.getElementById('normal');
            // 创建一个函数模拟ajax请求
            let ajax = content=>
                console.log('ajax:' + content);
            

            // 创建防抖函数
            let debounce = (fn,delay) => 
                return function(args)
                    let that = this;
                    let param = args;
                    // 每次事件触发 清除当前的timmer 然后重写调用
                    clearTimeout(fn.id);
                    fn.id = setTimeout(function()
                        fn.call(that,param)
                    ,delay)
                
            

            let deb_func = debounce(ajax,500)
            norInput.addEventListener('keyup',e=>
                deb_func(e.target.value)
            )
            
        
    </script>

    <input type="text" name="normal" id="normal">

</body>
</html>

上面的demo运行后,你会发下,用户如果停止输入后的一段时间才会发起ajax请求,而如果用户持续输入,则计时器会不断的刷新,再这个过程中并不会发生请求,直到用户停止输入,才会开始计时,时间一到,才会发送请求。

这样就能够有效的减少因为频繁发送请求给服务器带来过大的压力。

使用场景

  1. resize 事件或者scroll事件等,可以通过防抖减少触发次数
  2. 用户在输入框中频繁输入

节流

什么是节流

设置一个时间范围,在一定的时间范围内,仅允许执行一次执行一次事件的回调函数,也就是说只要在规定时间范围内,无论事件触发几次,都只能执行一次回调函数。

我们通过click事件来还原下事故现场:

<html>
<head>
    <meta charset="utf-8">
    <title>节流</title>
</head>
<body>

<input type="button" id="btn" value="点击">
<script type="text/javascript">

let oBtn = document.getElementById('btn');

let ajax = ()=>
    console.log("ajax发送请求")


oBtn.addEventListener('click',()=>
    ajax();
)

</script>
</body>
</html>

当用户每一次点击后,都会发送一次请求,点击不断,请求不断。如同生命不息,战斗不止。可想而知,一旦有人无聊的一直点击,那么请求次数将会变得很可观。

下面是我们根据节流的原理来实现的示例代码:

<html>
<head>
    <meta charset="utf-8">
    <title>问题演示</title>
</head>
<body>


    <script type="text/javascript">
        window.onload = function()
            // 获取元素 
            let oBtn = document.getElementById('normal');

            // 模拟ajax请求
            let ajax = ()=>
                console.log("ajax发送请求....")
            

            // 节流函数
            let throttle = (func,wait) =>
                var timeout ;
                var previous = 0;

                return function()
                    var _this = this;
                    args = arguments;
                    if(!timeout)
                        timeout = setTimeout(function()
                            timeout = null;
                            func.apply(_this,args);
                        ,wait)
                    
                
            
            let thro_func = throttle(ajax,3000);


            // 绑定事件  
            oBtn.addEventListener('click',()=>
                thro_func();
            )
        
    </script>

    <input type="button" name="normal" id="normal" value="点击">

</body>
</html>

通过上面的案例,我们可以做到,当用户点击一次后,计时器开始,这当中无论发生几次事件触发,都仅仅会执行一次回调。

当然,想要实现节流的方法不止使用定时器这一种方案,还可以选择使用时间戳,再或者其他方法也不是不行,本文的目的仅仅是为了阐述和说明节流防抖这两种减少服务器压力的方法而已。

使用场景

  1. 鼠标不断点击的情况
  2. 页面无限加载,每隔一段时间发起请求而不是用户停止滚动发起请求
  3. ...

以上是关于来聊聊JavaScript中的防抖和节流的主要内容,如果未能解决你的问题,请参考以下文章

javascript的防抖和节流

javascript的防抖和节流深入理解

事件的防抖和节流

VUE中的函数的防抖和节流 以及应用场景

浅谈 JS 的防抖和节流

lodash的防抖和节流方法