前端常用算法(一):防抖+节流

2024-06-04 9936阅读

目录

第一章 防抖

1.1 防抖(debounce)简介

1.2 应用场景

1.3 实现思路

1.4 手撕防抖代码

第二章 节流

2.1 节流(throttle)简介

2.2 应用场景

2.3 实现思路

2.4 手撕节流代码(方法:时间戳和计时器)

2.5 时间戳与计时器实现的区别

第三章 总结


第一章 防抖

1.1 防抖(debounce)简介

  • 场景:用户在一段时间频繁点击执行某个函数/事件,那么在这段时间,用户点击一次,计时器重新计时,当在这段时间内用户没有触发该函数/事件时,该函数/事件会在这段时间结束时执行,只执行最后一次。
  • 应用示例理解:回城被打断,玩家残血准备回城,需要3s回城成功,但是在这个3s的过程中,玩家又重新点击了回城,导致3s回城重新计算,再等3s。

    1.2 应用场景

    • 登录、发短信、发送post请求等按钮/事件避免用户点击太快,以致于发送了多次请求,需要防抖,最后一次发送请求即可;
    • 调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖;
    • input输入框获取到value值不需要输入一个字符就获取一次,可以使用防抖,让其输入结束之后再获取其值
    • 文本编辑器实时保存,当无任何更改操作一秒后进行保存。
    • ……

      1.3 实现思路

      前端常用算法(一):防抖+节流 第1张

      1.4 手撕防抖代码

      function debounce(func,delay) {
          // 定义一个定时器timer
          let timer = null
          return function() {
              const that = this
              const args = arguments
              // 防抖核心:每次触发事件计时器都会重新计时
              clearTimeout(timer)
              timer = setTimeout(()=>{
                  func.apply(that,args)
              },delay)
          }
      }
      • 例子:

        未调用防抖函数时:用户每在input输入/删除一个值,都会输出一个值;

            
            
                let inputDom = document.getElementById('input')
                //获取输入框的输入内容
                inputDom.oninput = function(){
                  console.log('this.value',this.value)
                }
            

         前端常用算法(一):防抖+节流 第2张

        调用防抖函数后:用户在input输入/删除一个值delay之后才,会输出一个值

            let inputDom = document.getElementById('input')
            //func 是执行函数,delay 是事件执行的延迟时间,毫秒
            function debounce(func,delay) {
                // 定义一个定时器timer
                let timer = null
                return function() {
                    const that = this
                    const args = arguments
                    // 防抖核心:每次触发事件计时器都会重新计时
                    clearTimeout(timer)
                    timer = setTimeout(()=>{
                       func.apply(that,args)
                    },delay)
                }
            }
            function handler() {
                console.log('this.value',this.value)
            }
            inputDom.addEventListener('input', debounce(handler, 1000))

        前端常用算法(一):防抖+节流 第3张

        第二章 节流

        2.1 节流(throttle)简介

        • 场景:用户在一段时间频繁点击执行某个函数/事件,那么在这段时间,用户点击一次/多次(调用事件),都不会影响计时器执行,并且该函数/事件只执行一次。
        • 应用示例理解:技能冷却中,玩家在某种情况下使用了闪现这个技能,但是这个技能的冷却时间是120s,在这段时间里,玩家遇到危险,想要再使用闪现这个技能,频繁的点击它,但是并没用,闪现不会执行,计时器依然还在倒计时,等到120s倒计时为0才能再使用一次闪现的技能。

          2.2 应用场景

          • 窗口调整
          • 页面滚动
          • 抢购和疯狂点击
          • 懒加载获取滚动条的位置
          • 鼠标连续不断地触发某事件(如点击),只在规定时间内触发一次
          • ……

            2.3 实现思路

            前端常用算法(一):防抖+节流 第4张

            2.4 手撕节流代码(方法:时间戳和计时器)

            // ---------------------节流1:使用时间戳---------------------
            //func 是事件处理程序,delay 是事件执行的延迟时间,单位:毫秒
            function throttle (func, delay) {
                //定义初始时间(开始触发事件的时间)
                let start = 0;
                return function () {
                    const that = this
                    const args = arguments
                    // 获取当前时间戳
                    let cur =Date.now()
                    // 时间间隔大于延迟时间则进入
                    if (cur - start >= delay) {
                        //执行事件处理程序
                        func.apply(that, args);
                        //更新初始时间
                        start = cur
                    }
                }
            }
            // ---------------------节流2:使用定时器---------------------
            //func 是事件处理程序,delay 是事件执行的延迟时间,单位:毫秒
            function throttle(func, delay){
                // 自定义一个定时器
                var timer = null;
                return function(){
                    var that = this;
                    var args = arguments
                    // timer为null表示可以发送请求了,否则还在请求中,不执行事件
                    if(!timer){
                        timer = setTimeout(function(){
                            //执行事件处理程序
                            func.call(that, args)
                            //事件执行完后把定时器清除掉,下次触发事件的时候再设置
                            timer = null;
                        }, delay)
                    }  
                }
            }
            •  例子:

              未调用节流函数时,每点击一次按钮,都会执行一次函数调用:

              发送了节流请求
              const button1Dom = document.getElementById('button1')
              button1Dom.addEventListener('click',function(){
                  console.log("节流:我发送了消息")
              })

              前端常用算法(一):防抖+节流 第5张

               使用节流函数之后,频繁的点击发送请求,它会在计时器结束之后再发,这段时间内点击发送一次请求之后,不会再发送请求:

              const button1Dom = document.getElementById('button1')
              // ---------------------节流1:使用时间戳---------------------
              //func 是事件处理程序,delay 是事件执行的延迟时间,单位:毫秒
              function throttle (func, delay) {
                  //定义初始时间(开始触发事件的时间)
                  let start = 0;
                  return function () {
                      const that = this
                      const args = arguments
                      // 获取当前时间戳
                      let cur =Date.now()
                      // 时间间隔大于延迟时间则进入
                      if (cur - start >= delay) {
                          //执行事件处理程序
                          func.apply(that, args);
                          //更新初始时间
                          start = cur
                      }
                  }
              }
              // ---------------------节流2:使用定时器---------------------
              //func 是事件处理程序,delay 是事件执行的延迟时间,单位:毫秒
              // function throttle(func, delay){
              //     // 自定义一个定时器
              //     var timer = null;
              //     return function(){
              //         var that = this;
              //         var args = arguments
              //         // timer为null表示可以发送请求了,否则还在请求中,不执行事件
              //         if(!timer){
              //             timer = setTimeout(function(){
              //                 //执行事件处理程序
              //                 func.call(that, args)
              //                 //事件执行完后把定时器清除掉,下次触发事件的时候再设置
              //                 timer = null;
              //             }, delay)
              //         }  
              //     }
              // }
              button1Dom.addEventListener('click',throttle(function(){
                  console.log("节流:我发送了消息")
              },1000))

              频繁的点击,降低了发送的频率: 

               前端常用算法(一):防抖+节流 第6张

              2.5 时间戳与计时器实现的区别

              最明显的区别就是在频繁点击的时候,会发现使用时间戳实现的节流会在调用的时候马上执行,而使用计时器实现会在时间段结束时执行

              第三章 总结

              • 所谓防抖,就是指触发事件后,在 n 秒后函数才会执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间;节流,就是指连续触发事件,但是在 n 秒中只执行一次函数。
              • 函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。

    免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

    目录[+]