JavaScript 中的简单节流阀

新手上路,请多包涵

我正在寻找 JavaScript 中的简单节流阀。我知道像 lodash 和 underscore 这样的库有它,但只有一个功能,包含这些库中的任何一个都太过分了。

我也在检查 jQuery 是否具有类似的功能 - 找不到。

我找到了一个工作油门,这是代码:

 function throttle(fn, threshhold, scope) {
  threshhold || (threshhold = 250);
  var last,
      deferTimer;
  return function () {
    var context = scope || this;

    var now = +new Date,
        args = arguments;
    if (last && now < last + threshhold) {
      // hold on to it
      clearTimeout(deferTimer);
      deferTimer = setTimeout(function () {
        last = now;
        fn.apply(context, args);
      }, threshhold);
    } else {
      last = now;
      fn.apply(context, args);
    }
  };
}

这个问题是:它在节流时间完成后再次触发该功能。所以让我们假设我做了一个油门,在按键时每 10 秒触发一次——如果我按键 2 次,它仍然会在 10 秒完成后触发第二次按键。我不想要这种行为。

原文由 Mia 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 367
2 个回答

我会使用 underscore.jslodash 源代码来找到此功能的经过良好测试的版本。

这是下划线代码的略微修改版本,用于删除对 underscore.js 本身的所有引用:

 // Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time. Normally, the throttled function will run
// as much as it can, without ever going more than once per `wait` duration;
// but if you'd like to disable the execution on the leading edge, pass
// `{leading: false}`. To disable execution on the trailing edge, ditto.
function throttle(func, wait, options) {
  var context, args, result;
  var timeout = null;
  var previous = 0;
  if (!options) options = {};
  var later = function() {
    previous = options.leading === false ? 0 : Date.now();
    timeout = null;
    result = func.apply(context, args);
    if (!timeout) context = args = null;
  };
  return function() {
    var now = Date.now();
    if (!previous && options.leading === false) previous = now;
    var remaining = wait - (now - previous);
    context = this;
    args = arguments;
    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;
  };
};

请注意,如果您不需要所有下划线支持的选项,则可以简化此代码。

请在下面找到此功能的一个非常简单且不可配置的版本:

 function throttle (callback, limit) {
    var waiting = false;                      // Initially, we're not waiting
    return function () {                      // We return a throttled function
        if (!waiting) {                       // If we're not waiting
            callback.apply(this, arguments);  // Execute users function
            waiting = true;                   // Prevent future invocations
            setTimeout(function () {          // After a period of time
                waiting = false;              // And allow future invocations
            }, limit);
        }
    }
}

编辑 1:删除了另一个对下划线的引用,感谢@Zettam 的评论

编辑 2:添加了关于 lodash 和可能的代码简化的建议,感谢 @lolzery @wowzery 的评论

编辑 3:由于普遍要求,我添加了一个非常简单的、不可配置的函数版本,改编自@vsync 的评论

原文由 Clément Prévost 发布,翻译遵循 CC BY-SA 4.0 许可协议

那这个呢?

 function throttle(func, timeFrame) {
  var lastTime = 0;
  return function () {
      var now = Date.now();
      if (now - lastTime >= timeFrame) {
          func();
          lastTime = now;
      }
  };
}

简单的。

您可能有兴趣查看 源代码

原文由 smartmouse 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏