函数防抖与函数节流

函数防抖(debounce

概念:就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

  • 简单的说,当一个动作连续触发,则只执行最后一次。

常见实用场景,有滚动加载、搜索框输入、窗口大小拖拽 Resize。

函数防抖的应用场景(连续的事件,只需触发一次回调):

  • 搜索框搜索输入。只需用户最后一次输入完,再发送请求
  • 手机号、邮箱验证输入检测
  • 窗口大小Resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。

  • 为什么需要函数防抖:
    • 前端开发过程中,有一些事件,常见的例如,**onresize**,**scroll**,**mousemove** ,**mousehover** 等,会被频繁触发(短时间内多次触发),不做限制的话,有可能一秒之内执行几十次、几百次,如果在这些函数内部执行了其他函数,尤其是执行了操作 DOM 的函数(浏览器操作 DOM 是很耗费性能的),那不仅会浪费计算机资源,还会降低程序运行速度,甚至造成浏览器卡死、崩溃。这种问题显然是致命的。除此之外,短时间内重复的 ajax 调用不仅会造成数据关系的混乱,还会造成网络拥塞,增加服务器压力,显然这个问题也是需要解决的。

  • 怎么做
    • 函数防抖的要点,是需要一个 **setTimeout** 来辅助实现,延迟运行需要执行的代码。如果方法多次触发,则把上次记录的延迟执行代码用 **clearTimeout** 清掉,重新开始计时。若计时期间事件没有被重新触发,等延迟时间计时完毕,则执行目标代码。

实例:

<body>

    <span id="span"></span>

    <script>

        let count=0;

        function demo(params) {

            count++;

            span.innerHTML=count;   

        }

        function debounce(fn,delay) {

            let timer;

            return function () {  //定义一个匿名函数,return返回的是一个函数,

                if(timer){    //判断timer是否有值

                    clearTimeout (timer);    //清除掉之前的定时器的数据

                }

                timer=setTimeout(fn,delay);   //重新生成定时器,也就是说我定义的一秒,就重新开始计时一秒

            }

        }

        //原理:只有当1秒内没有重新触发这个事件才可以进行计算

        window.addEventListener("resize",debounce(demo,1000))    //当屏幕尺寸发生改变的时候,触发该事件,

    </script>

</body>

函数节流(throttle

概念:指连续触发事件多次,但是在n秒内只执行一次函数,

函数节流的应用场景(间隔一段时间执行一次回调):

  • 滚动加载,加载更多或滚到底部监听
  • 谷歌搜索框,搜索联想功能
  • 高频点击提交,表单重复提交
<body>

    <div id="div1">

    </div>

    <span id="span"></span>

    <script>

        let count=0;

        function fn(params) {

            if(count===50){

                return;

            }

            count++;

            span.innerHTML=count;

        }

        function throttle(fn,delay) {

            let status=true;   //标识   是否可以干活

            return function (params) {

                if(!status){    //判断是否可以操作

                    return

                }

                status=false;    //干活之后设置状态,为不允许在操作

                setTimeout(()=>{

                    fn();    //重新调用fn函数

                    status=true;    //又开始干活

                },delay)

            }

        }



        div1.onmousemove=throttle(fn,1000)

    </script>

</body>

函数防抖和函数节流异同比较

相同点:

  • 都可以通过使用 setTimeout 实现。
  • 目的都是,降低回调执行频率。节省计算资源。

不同点:

  • 函数防抖,在一段连续操作结束后,处理回调,利用 clearTimeout 和 setTimeout 实现。函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能。
  • 函数防抖关注一定时间连续触发,只在最后执行一次,而函数节流侧重于一段时间内只执行一次。

 为了辅助理解,我们首先通过一个可视化的工具,感受一下三种环境(正常情况、函数防抖情况 debounce、函数节流 throttle)下,对于mousemove事件回调的执行情况。

 

竖线的疏密代表事件执行的频繁程度。可以看到,正常情况下,竖线非常密集,函数执行的很频繁。而debounce(函数防抖)则很稀疏,只有当鼠标停止移动时才会执行一次。throttle(函数节流)分布的较为均已,每过一段时间就会执行一次。

想看相信的可以去看看涂鸦码龙写的实例解析防抖动(Debouncing)和节流阀(Throttling) https://jinlong.github.io/2016/04/24/Debouncing-and-Throttling-Explained-Through-Examples/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值