zoukankan      html  css  js  c++  java
  • 节流(throttle)与防抖(debounce)

    运行案例

    运行代码

    <div id="content"
      style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;">
    </div>
    <script>
      let num = 1;
      const content = document.getElementById('content');
      function count() {
        content.innerHTML = num++;
      };
      content.onmousemove = count;
    </script>
    

    运行效果

    mousemove

    当鼠标在 div(灰色)区域中移动的时候会持续地去触发该事件导致频繁执行函数。

    防抖(debounce)

    所谓防抖,就是指触发事件后 n 秒后才执行函数,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

    防抖函数分为非立即执行版和立即执行版。

    防抖(debounce)非立即执行版:

    非立即执行版触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

    /**
    * @description: 
    * @param {Function}  func 事件函数
    * @param {Number}    wait 事件设置的延迟事件 (1000 = 1 秒)
    * @return (Function): 返回新的 debounced(防抖动)函数。
    *
    */
    function debounce(func, wait) {
      let timeout;
      return function () {
        /**
        *  const context = this;
        *  const args = [...arguments];
        *  这两行代码来获取 this 和 参数,是为了让 防抖(debounce) 函数最终返回的函数 this 指向不变以及依旧能接受到携带的参数。
        *
        */  
        const context = this;
        const args = [...arguments];
        if (timeout) clearTimeout(timeout);
        timeout = setTimeout(() => {
          func.apply(context, args)
        }, wait);
      }
    }
    
    /**
    *  content.onmousemove = count;
    *  修改mousemove事件绑定的函数
    *  content.onmousemove = debounce(count,1000);
    *
    */
    content.onmousemove = debounce(count,1000);
    

    运行效果

    nomousermove

    当鼠标在 div(灰色)区域中移动的时候不会触发执行函数,需要在停留在触发事件后函数 1 秒后才执行,而如果触发事件后的 1 秒内移动鼠标,则会重新计算函数执行时间。

    防抖(debounce)立即执行版:

    /**
    * @description: 
    * @param {Function}  func 事件函数
    * @param {Number}    wait 事件设置的延迟事件 (1000 = 1 秒)
    * @return (Function): 返回新的 debounced(防抖动)函数。
    *
    */
    function debounce(func,wait) {
      let timeout;
      return function () {
          const context = this;
          const args = [...arguments];
          if (timeout) clearTimeout(timeout);
          const callNow = !timeout;
          timeout = setTimeout(() => {
              timeout = null;
          }, wait)
          if (callNow) func.apply(context, args)
      }
    }
    
    /**
    *  content.onmousemove = count;
    *  修改mousemove事件绑定的函数
    *  content.onmousemove = debounce(count,1000);
    *
    */
    content.onmousemove = debounce(count,1000);
    

    运行结果

    首次会运行一次。当鼠标在 div(灰色)区域中移动的时候不会触发执行函数,需要在停留在触发事件后函数 1 秒后才执行,而如果触发事件后的 1 秒内移动鼠标,则会重新计算函数执行时间。

    防抖函数整合版

    /**
    * @desc 函数防抖
    * @param func (function) 函数
    * @param wait (number) 延迟执行毫秒数
    * @param immediate (boolean) true 表立即执行,false 表非立即执行
    * @return (Function): 返回新的 debounced(防抖动)函数。
    *
    */
    function debounce(func, wait, immediate) {
        let timeout;
        let result;
        return function () {
            const context = this;
            const args = arguments;
            if (timeout) clearTimeout(timeout);
            if (immediate) {
                const callNow = !timeout;
                timeout = setTimeout(function () {
                    timeout = null;
                }, wait)
                if (callNow) result = func.apply(context, args)
            }
            else {
                timeout = setTimeout(function () {
                    func.apply(context, args)
                }, wait);
            }
            return result;
        }
    }
    

    Lodash库防抖(debounce)函数

    /**
    *  @desc 创建一个 debounced(防抖动)函数,该函数会从上一次被调用后,延迟 `wait` 毫秒后调用 `func` 方法。 
    *  @param func (Function): 要防抖动的函数。
    *  @param [wait=0] (number): 需要延迟的毫秒数。
    *  @param [options={}] (Object): 选项对象。
    *  @param [options.leading=false] (boolean): 指定在延迟开始前调用。
    *  @param [options.maxWait] (number): 设置 func 允许被延迟的最大值。
    *  @param [options.trailing=true] (boolean): 指定在延迟结束后调用。
    *  @return (Function): 返回新的 debounced(防抖动)函数。
    *
    */
    
    _.debounce(func, [wait=0], [options={}])
    

    _.debounce提供一个 options(选项) 对象决定如何调用 func 方法,主要是以下三个:

    • leading,函数在每个等待时延的开始被调用,默认值为false
    • trailing,函数在每个等待时延的结束被调用,默认值是true
    • maxwait,最大的等待时间,因为如果debounce的函数调用时间不满足条件,可能永远都无法触发,因此增加了这个配置,保证大于一段时间后一定能执行一次函数。

    leadingtrailing的组合,可以实现不同的调用效果:

    • leading-falsetrailing-true:默认情况,即在延时结束后才会调用函数。
    • leading-truetrailing-true:在延时开始时就调用,延时结束后也会调用。
    • leading-true , trailing-false:只在延时开始时调用。

    节流(throttle)

    连续触发事件但只会在规定时间内只执行一次函数。 节流会稀释函数的执行频率。
    

    节流(throttle)时间戳版:

    /**
    * @desc 函数节流
    * @param func (function) 函数
    * @param wait (number) 延迟执行毫秒数
    * @return (Function): 返回新的 throttle(防抖动)函数。
    *
    */
    function throttle(func, wait) {
        var previous = 0;
        return function() {
            let now = Date.now();
            let context = this;
            let args = arguments;
            if (now - previous > wait) {
                func.apply(context, args);
                previous = now;
            }
        }
    }
    
    /**
    *  content.onmousemove = count;
    *  修改mousemove事件绑定的函数
    *  content.onmousemove = throttle(count,1000);
    *
    */
    content.onmousemove = throttle(count,1000);
    

    运行结果

    throttle

    当鼠标在 div(灰色)区域中移动的时候会持续触发事件,函数会立即执行,并且每 1s 执行一次。

    节流(throttle)定时器版:

    /**
    * @desc 函数节流
    * @param func (function) 函数
    * @param wait (number) 延迟执行毫秒数
    * @return (Function): 返回新的 throttle(防抖动)函数。
    *
    */
    function throttle(func, wait) {
        let timeout;
        return function() {
            let context = this;
            let args = arguments;
            if (!timeout) {
                timeout = setTimeout(() => {
                    timeout = null;
                    func.apply(context, args)
                }, wait)
            }
    
        }
    }
    
    /**
    *  content.onmousemove = count;
    *  修改mousemove事件绑定的函数
    *  content.onmousemove = throttle(count,1000);
    *
    */
    content.onmousemove = throttle(count,1000);
    

    运行结果

    setThrottle

    当鼠标在 div(灰色)区域中移动的时候会持续触发事件,函数会立即执行,并且每 1s 执行一次。在停止触发事件后,函数还会再执行一次。

    节流函数整合版:

    /**
    *  @desc 函数节流
    *  @param func 函数
    *  @param wait 延迟执行毫秒数
    *  @param type 1 表时间戳版,2 表定时器版
    *  @return (Function): 返回新的 throttle(防抖动)函数。
    *
    */
    function throttle(func, wait ,type) {
        if(type===1){
            let previous = 0;
        }else if(type===2){
            let timeout;
        }
        return function() {
            let context = this;
            let args = arguments;
            if(type===1){
                let now = Date.now();
                if (now - previous > wait) {
                    func.apply(context, args);
                    previous = now;
                }
            }else if(type===2){
                if (!timeout) {
                    timeout = setTimeout(() => {
                        timeout = null;
                        func.apply(context, args)
                    }, wait)
                }
            }
    
        }
    }
    

    Lodash库节流(throttle)函数

    /**
    *  func (Function): 要节流的函数。
    *  @param [wait=0] (number): 需要节流的毫秒。
    *  @param [options={}] (Object): 选项对象。
    *  @param [options.leading=true] (boolean): 指定调用在节流开始前。
    *  @param [options.trailing=true] (boolean): 指定调用在节流结束后。
    *  @return (Function): 返回节流的函数	
    /
    _.throttle(func, [wait=0], [options={}])
    

    防抖(throttle)就是设置了maxwait的节流(debounce)。防抖(throttle)同样提供了leadingtrailing参数,与节流(debounce)含义相同。

    _.throttle提供一个 options(选项) 对象决定如何调用 func 方法,主要是以下三个:

    • leading,函数在每个等待时延的开始被调用,默认值为false
    • trailing,函数在每个等待时延的结束被调用,默认值是true

    leadingtrailing的组合,可以实现不同的调用效果:

    • leading-falsetrailing-true:默认情况,即在延时结束后才会调用函数。
    • leading-truetrailing-true:在延时开始时就调用,延时结束后也会调用。
    • leading-true , trailing-false:只在延时开始时调用。

    参考文章

    https://github.com/mqyqingfeng/Blog/issues/22

    https://github.com/mqyqingfeng/Blog/issues/26

    https://blog.csdn.net/duola8789/article/details/78871789

  • 相关阅读:
    Fedora 19安装Fcitx输入法并安装搜狗输入法资源包
    mac 功能修改。。。。
    Zend Studio / Ecliplse插件StartExplorer
    关于更改apache和mysql的路径的问题..
    解决fedora64下vim不能语法着色问题
    正则例一
    PHP中使用正则表达式详解 preg_match() preg_replace() preg_mat
    C语言正则表达式详解 regcomp() regexec() regfree()详解
    正则19-20
    正则表达式教程:30分钟让你精通正则表达式语法
  • 原文地址:https://www.cnblogs.com/Scooby/p/13564126.html
Copyright © 2011-2022 走看看