防抖和节流

这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战html

前置知识

setTimeout函数ajax

setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式。浏览器

提示:  1000 毫秒= 1 秒。 、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、 setTimeout.pngmarkdown

clearTimeout函数 clearTimeout() 方法可取消由 setTimeout() 方法设置的 timeout。 clearTimeout() 方法的参数必须是由 setTimeout() 返回的 ID 值。app

语法

image-20210808134440985

clearTimeout.png setInterval函数异步

超时值是指在指定时间以后执行代码,间歇时间值是指每隔指定的时间就执行一次代码。设置超时调用的方法是setTimeout(),设置间歇调用的方法是setInterval()。函数

setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用做 clearInterval() 方法的参数。post

函数防抖

概念: 在事件被触发n秒后再执行回调,若是在这n秒又被触发,则从新计时ui

举例:点击触发事件函数this

请输入数字:<input id="normal"></input>
​
<script>
function ajax(value) {
            console.log('ajax 请求:', value);
}
let emitBussiness = document.getElementById('normal')
emitBussiness.addEventListener('keyup', function (e) {
    ajax(e.target.value)
})
</script>
复制代码

没有防抖.png 这个函数的做用是每按下一个按键,就输出当前输入框里的值。

假设咱们想输入一串字符,而后发送请求查询这串字符,但这串字符还没输完就发送了不少个请求,有些不符合实际状况。

接下来,咱们在这个函数中加入防抖。

请输入数字:<input id="normal"></input>
    
    <script>
        function ajax(value) {
            console.log('ajax 请求:', value);
        }
        function delayAjax(fun, delay) {
            return function (val) {
                let that = this
                let args = val
                //console.log('before', fun.setId);
                clearTimeout(fun.setId)
                fun.setId = setTimeout(() => {
                                fun.call(that, val)
                            }, delay)
                //console.log('after', fun.setId);
            }
        }
        let emitBussiness = document.getElementById('normal')
        let funD = delayAjax(ajax, 1000)
        emitBussiness.addEventListener('keyup', function (e) {
            funD(e.target.value)
        })
    </script>
复制代码

注意:clearTimeout(fun.setId) 这条语句的位置要在下面的setTimeout函数以前。这时由于第一次按键,fun.setId保存的值是undefined,第二次按键,fun.setId保存的值是1,第三次按键,fun.setId保存的值是2,... 也就是说,在执行setTime函数以前,fun.SetId保存的是上一次setTimeout的返回值。而咱们的需求也正是当距离上一次按键的时间间隔不到指定事件就取消上一次的请求。

防抖.png 首先,按下按键1,1秒以内没有按下别的按键,输出'ajax 请求:1';按下按键2,1秒以内没有按下别的按键,输出'ajax 请求:12';接着,快速按下三、四、五、6,间隔时间小于1秒,接着等待1秒后,输出'ajax 请求:123456';可见咱们的防抖起了做用。

咱们加入了防抖之后,当你在频繁的输入时,并不会发送请求,只有当你在指定间隔内没有输入时,才会执行函数。若是中止输入可是在指定间隔内又输入,会从新触发计时。

函数节流

概念: 规定在一个单位时间内,只能触发一次函数。若是这个单位时间内触发屡次函数,只有一次生效。

指当连续触发事件时,在 n 秒中只执行一次函数。

好比,咱们一直喝水,但不是一喝水就上厕所,而是每隔一段时间就去上厕所。

初始html代码:(没有节流)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="content"
        style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;width:100%">
    </div>
    <script>
        let num = 0;
        const content = document.getElementById('content');
        function count() {
            // 一些异步请求或者别的代码
            content.innerHTML = num++;
        };
        content.onmousemove = count;
    </script> 
</body>
</html>
复制代码

实现1--时间戳:

<div id="content"
        style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;width:100%">
    </div>
    <script>
        // 第一次触发,最后一次不触发
        // 顾头不顾尾
        
        // 当触发事件时,执行函数时取出当前时间戳,用当前时间戳减去一开始设置的时间戳,若是时间差值>设置的时间周期,就执行函数并更新当前时间为时间戳。
        function throttle(func, wait) {
            let context, args;
            //以前的时间戳
            let old = 0;
            return function() {
                // 若是不对this作处理,func里面的this指向window,但咱们要让this指向当前的div对象
                context = this
                args = arguments
                // 获取当前时间戳
                let now =  new Date().valueOf();
                if ( now - old > wait ) {
                    // 当即执行
                    func.apply(content, args)
                    old = now
                }
            }
        }

        let num = 0;
        const content = document.getElementById('content');
        function count() {
            // 一些异步请求或者别的代码
            content.innerHTML = num++;
        };
        content.onmousemove = throttle(count, 2000);
    </script> 
复制代码

实现2--定时器:

<div id="content"
        style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;width:100%">
    </div>
    <script>
        // 顾尾不顾头 
        // 第一次不会触发,最后一次会触发

        // 触发事件时,咱们会设置一个定时器timeout,再触发这个事件时,若是timeout存在,就不执行;直至执行后定时器设置为null。
        function throttle(func, wait) {
            let context, args, timeout;
            

            return function() {
                context = this
                args = arguments
                if(!timeout) {
                    timeout = setTimeout(() => {
                        timeout = null
                        func.apply(context, args)
                    }, wait)
                }
        
            }
        }

        let num = 0;
        const content = document.getElementById('content');
        function count() {
            // 一些异步请求或者别的代码
            content.innerHTML = num++;
        };
        content.onmousemove = count;
    </script> 
复制代码

总结

  • 函数防抖和函数节流都是防止某一时间频繁触发,可是原理却不同。
  • 函数防抖是某一段时间内只执行一次,而函数节流是间隔时间执行。

应用场景

防抖

  • search搜索联想,用户在不断输入值时,用防抖来节约请求资源。
  • 不断的调整浏览器窗口大小会不断的触发resize事件,用防抖来让其只触发一次。

节流

  • 鼠标不断点击触发,mousedown(单位时间内只触发一次)
  • 监听滚动事件,好比是否滑到底部自动加载更多,用throttle来判断

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

参考

连接:juejin.cn/post/684490…

连接:juejin.cn/post/684490…