防抖和节流(立即执行/非立即执行/立即取消等待/传参)


先看看概念

函数防抖(debounce):

在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时;典型的案例就是输入搜索:输入结束后n秒才进行搜索请求,n秒内又输入的内容,就重新计时。

应用场景:

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

     

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <button id="btn">第一次点击按钮立即执行 接下来 防抖</button>
        <button id="btn2">终止</button>
    </body>
    <script>
      var btn = document.getElementById('btn');
      let b= 2
      let f =  debounce_2(sayHi,2000,true)
      btn.addEventListener('click',()=>{
        f(b)
      })
      btn2.addEventListener('click',()=>{
        f.stop()
      })
      // 防抖(非立即执行)
      function debounce_1(fn,wait){
        let timer = null;
        return function(){
          clearTimeout(timer);
          timer = setTimeout(() => {
            fn.apply(this,arguments)
          },wait)
        }
      }
    
      // 防抖立即执行
      function debounce_2(fn,wait){
        let time = null
        let flag = true
        return function (){
          clearTimeout(time)
          if(flag){
            fn.apply(this,arguments)
            flag = false
          }
          time = setTimeout(()=>{
            flag = true
          },wait)
        }
      }
    
      // 防抖自定义第一次是否执行
      function debounce_3(fn,wait,isImmediate = true){
        let flag = true
        let time = null
        if(isImmediate){
          if(flag){
            return function (){
              fn.apply(this,arguments)
              flag = false
            }
          }
          clearTimeout(time)
          time = setTimeout(()=>{
            flag = true
          },wait)
        }
        return function (){
          clearTimeout(time);
          time = setTimeout(() => {
            fn.apply(this,arguments)
          },wait)
        }
      }
    
      // 防抖自定义第一次是否执行 且可中断执行
      function debounce_4(fn, wait = 500, isImmediate = false) {
        // 计时器
        let timerId = null;
        // flag为真时立即执行
        let flag = true;
        let resultFunc = null;
        if (isImmediate) {
          // 立即执行
          //  例如:用户在输入框中输入字符,输入第一个字符时,立即执行一次
          // 之后,最终间隔超过2秒后,才执行补全查询
          resultFunc = function () {
            let context = this;
    
            clearTimeout(timerId);
            if (flag) {
              fn.apply(context, arguments);
              flag = false
            }
            timerId = setTimeout(() => {
              flag = true
            }, wait)
          }
    
          resultFunc.cancel = function () {
            // 例如,用户打字很快,然后输入完成后,未达到两秒钟就移动鼠标
            // 此时输入框失去焦点,触发取消等待方法,立刻执行补全查询操作并显示结果出来
    
            console.log("立即取消等待")
            clearTimeout(timerId);
            flag = true;
          }
    
        } else {
          // 不立即执行
          //  例如:用户在输入框中输入字符,最终间隔超过2秒后,才执行补全查询
    
          resultFunc = function () {
            let context = this;
    
            clearTimeout(timerId);
            timerId = setTimeout(() => {
              fn.apply(context, arguments)
            }, wait)
          }
    
          resultFunc.cancel = function () {
            console.log("立即取消等待");
            clearTimeout(timerId);
          }
        }
        return resultFunc;
      }
    
      function sayHi(b) {
        console.log(b)
        console.log('防抖')
      }
    </script>
    </html>

     

     

函数节流(throttle):

规定在一个单位时间内,只能触发一次函数,如果这个单位时间内触发多次函数,只有一次生效; 典型的案例就是鼠标不断点击触发,规定在n秒内多次点击只有一次生效。

应用场景:

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

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <button id="btn">第一次点击按钮立即执行 接下来 节流</button>
    <button id="btn2">终止</button>
    </body>
    <script>
      var btn = document.getElementById('btn');
      let b= 2
      let f =  throttle_4(sayHi,3000)
      btn.addEventListener('click',()=>{
        f(b)
        // throttle_3(sayHi,3000)(b) 不能这么写,因为这相当于每次都重新声明了这个节流函数
      })
      btn2.addEventListener('click',()=>{
        f.stop()
      })
      //节流(非立即执行)
      function throttle_1(fn,wait){
        let flag = true;
        return function(){
          if(flag == true){
            flag = false
            var timer = setTimeout(() => {
              fn.apply(this,arguments)
              flag = true
            },wait)
          }
        }
      }
      //节流(立即执行)
      function throttle_2(fn,wait){
        var flag = true;
        var timer = null;
        return function(){
          if(flag) {
            fn.apply(this,arguments);
            flag = false;
            timer = setTimeout(() => {
              flag = true
            },wait)
          }
        }
      }
      //节流(自定义是否立即执行)
      function throttle_3(fn,wait = 500,isImmediate = false){
        let flag = true;
        let timer = null;
    
        if(isImmediate){
          return function(){
            if(flag) {
              fn.apply(this,arguments);
              flag = false;
              timer = setTimeout(() => {
                flag = true
              },wait)
            }
          }
        }
    
        return function(){
          if(flag == true){
            flag = false
            var timer = setTimeout(() => {
              fn.apply(this,arguments)
              flag = true
            },wait)
          }
        }
      }
      //节流(自定义是否立即执行且可以中断)
      function throttle_4(fn, wait = 500, isImmediate = false) {
        let flag = true;
        let timer = null;
    
        let resultFunc = null;
    
        if (isImmediate) {
          // 立即执行
          resultFunc = function () {
            if (flag) {
              fn.apply(this, arguments);
              flag = false;
              timer = setTimeout(() => {
                flag = true
              }, wait)
            }
          }
    
          resultFunc.cancel = function () {
            console.log("立即取消等待")
            clearTimeout(timer)
          }
        } else {
          // 不立即执行
          resultFunc = function () {
    
            if (flag == true) {
              flag = false
              timer = setTimeout(() => {
                fn.apply(this, arguments)
                flag = true
              }, wait)
            }
          }
    
          resultFunc.cancel = function () {
            console.log("立即取消等待")
            clearTimeout(timer);
            flag = true;
          }
        }
    
        return resultFunc;
    
      }
      
      function sayHi(b) {
        console.log(b)
        console.log('节流')
      }
    </script>
    </html>

     

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM