zoukankan      html  css  js  c++  java
  • Underscore.js 中 _.throttle 和 _.debounce 的差异

     
    两个方法都是用来控制事件的频率的,在mousemove,resize等这种高频率触发事件中,控制其响应频率可以明显提高程序的流畅性,减少资源的占用。

    通过分析其源代码:

    _.throttle方法源码

    /**
     * 频率控制 返回函数连续调用时,func 执行频率限定为 次 / wait
     *
     * @param  {function}   func      传入函数
     * @param  {number}     wait      表示时间窗口的间隔
     * @param  {object}     options   如果想忽略开始边界上的调用,传入{leading: false}。
     *                                如果想忽略结尾边界上的调用,传入{trailing: false}
     * @return {function}             返回客户调用函数  
     */
    _.throttle = function(func, wait, options) {
      var context, args, result;
      var timeout = null;
      // 上次执行时间点
      var previous = 0;
      if (!options) options = {};
      // 延迟执行函数
      var later = function() {
        // 若设定了开始边界不执行选项,上次执行时间始终为0
        previous = options.leading === false ? 0 : _.now();
        timeout = null;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      };
      return function() {
        var now = _.now();
        // 首次执行时,如果设定了开始边界不执行选项,将上次执行时间设定为当前时间。
        if (!previous && options.leading === false) previous = now;
        // 延迟执行时间间隔
        var remaining = wait - (now - previous);
        context = this;
        args = arguments;
        // 延迟时间间隔remaining小于等于0,表示上次执行至此所间隔时间已经超过一个时间窗口
        // remaining大于时间窗口wait,表示客户端系统时间被调整过
        if (remaining <= 0 || remaining > wait) {
          clearTimeout(timeout);
          timeout = null;
          previous = now;
          result = func.apply(context, args);
          if (!timeout) context = args = null;
        //如果延迟执行不存在,且没有设定结尾边界不执行选项
        } else if (!timeout && options.trailing !== false) {
          timeout = setTimeout(later, remaining);
        }
        return result;
      };
    };

    _.debounce方法源码

    /**
     * 空闲控制 返回函数连续调用时,空闲时间必须大于或等于 wait,func 才会执行
     *
     * @param  {function} func        传入函数
     * @param  {number}   wait        表示时间窗口的间隔
     * @param  {boolean}  immediate   设置为ture时,调用触发于开始边界而不是结束边界
     * @return {function}             返回客户调用函数
     */
    _.debounce = function(func, wait, immediate) {
      var timeout, args, context, timestamp, result;
     
      var later = function() {
        // 据上一次触发时间间隔
        var last = _.now() - timestamp;
     
        // 上次被包装函数被调用时间间隔last小于设定时间间隔wait
        if (last < wait && last > 0) {
          timeout = setTimeout(later, wait - last);
        } else {
          timeout = null;
          // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
          if (!immediate) {
            result = func.apply(context, args);
            if (!timeout) context = args = null;
          }
        }
      };
     
      return function() {
        context = this;
        args = arguments;
        timestamp = _.now();
        var callNow = immediate && !timeout;
        // 如果延时不存在,重新设定延时
        if (!timeout) timeout = setTimeout(later, wait);
        if (callNow) {
          result = func.apply(context, args);
          context = args = null;
        }
     
        return result;
      };
    };

    _.throttle像一个节流阀,在预设时间内,不管事件触发多少次,只执行一次,而_.debounce则像电梯,只有当两次事件触发的间隔大于预设时间,才会触发事件。如果电梯里有人进来,开始等待。如果又人进来,重新计时等待,直到超过预设时间,开始执行

  • 相关阅读:
    html 复习
    用openrowset连接远程SQL或插入数据
    查询SQL中的text类型字段内容,让其显示完整
    删除CheckBoxList未选中或选中的CheckBox选项
    RSA的加解密过程(转自CSDN,学习用)
    创建与删除SQL约束或字段约束。
    根据DataGrid绑定的列的SortException字段进行排序
    尽量避免IE拦截弹出窗口的代码,与ListBox的双击事件结合。
    比较好看的滚动条样式和按钮样式和文本框样式
    JS控制按钮10秒钟后才能正常使用
  • 原文地址:https://www.cnblogs.com/lingtong/p/4072869.html
Copyright © 2011-2022 走看看