关于underscore源码中throttle函数的疑惑?

发布于 2022-09-06 21:13:05 字数 1433 浏览 28 评论 0

_.throttle = function(func, wait, options) {
    var context, args, result;
    var timeout = null;
    var previous = 0;
    if (!options) options = {};
    var later = function() {
      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;
      // 如果超过了wait时间,那么就立即执行
      if (remaining <= 0 || remaining > wait) {
        if (timeout) {
          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;
    };
  };

如上所示,在underscore中可以传入leading为false来控制第一次是否立即执行,那么我想问一下if (!previous && options.leading === false) previous = now;这句到底是什么意思?为什么options.leading为false的时候每次都要把now赋值给previous?这样now - previous不是必然为0?这样remaining就是wait了。
但是在options.leading不为false,也就是第一次立即执行的时候,为什么previous却是上次执行的later函数里面记录的时间,这个时候now - previous肯定是大于0的,这样remaining岂不是永远小于wait?
为什么这两种情况下最后的remaining值却不一样?这是怎么处理的?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

撧情箌佬 2022-09-13 21:13:05

其实从代码上来看,当设置了option.leading=false的时候:

  1. 首次调用函数时,previous=now,即remaining=wait,所以会延迟wait时间调用
  2. 在延迟的wait时间内,previous维持在上次的now值,也就是函数调用的时间,无法调用函数
  3. 在wait时间过后,setTimeout回调later,又previous=0
  4. 下次调用函数的时候,由于previous===0,因此又有previous=now,回到步骤1

也就是在设置了option.leading=false的时候,不只是令首次函数调用被延迟,而是每一次函数调用都被延迟。

至于remaining的值,始终为要调用还需要等待的时间。函数的延迟调用方式是通过修改previous的赋值方式来控制的。

下面是官方的文档:

By default, throttle will execute the function as soon as you call it for the first time, and, if you call it again any number of times during the wait period, as soon as that period is over. If you'd like to disable the leading-edge call, pass {leading: false}

翻译一下就是:

默认情况下, throttle返回的函数在你第一次调用的时候都会尽快执行, 并且, 不管你在延迟期内调用函数多少次(都会失效), 直到延迟期结束. 如果你想要禁止首次调用, 传递参数 {leading: false}

然而我觉得这个文档很有问题。因为第一次调用也没有被禁止,而是被延迟了。后续的所有函数调用也都变成了延迟调用的形式。如果有什么不对的地方希望可以跟我交流一下。

花辞树 2022-09-13 21:13:05

!previous条件被你吃了?怎么会每次都为now呢?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文