下划线throttle+确保最后一次调用



Undercore提供了方法throttle。从他们的文档:

创建并返回传递函数的一个新的节流版本,当重复调用该版本时,每等待毫秒最多只能调用一次原始函数。对于发生速度超过您所能跟上的速度的速率限制事件非常有用。

现在想象一下自动完成表单的情况。这意味着,如果在100ms窗口内键入"abc",则只发送对"a"的搜索,而不发送"bc"。

这是undercore.js方面的严重疏忽吗?你认为什么是清洁的解决方案?

对于此用例,您可能希望使用以下"buffer"函数,该函数将仅应用等待窗口内的最后一次调用。

https://gist.github.com/2484196

_.buffer = function(func, wait, scope) {
  var timer = null;
  return function() {
    if(timer) clearTimeout(timer);
    var args = arguments;
    timer = setTimeout(function() {
      timer = null;
      func.apply(scope, args);
    }, wait);
  };
};

啊,我没有正确阅读文档!的一个函数。

var test = _.debounce(function() { console.log('foo'); }, 3000);

然后,如果您多次调用test(),您会注意到,只有在上一次调用后的三秒钟后,才会调用该函数。

这正是我们想要的。。。并且没有注意到就在文档上CCD_ 2的正下方。

Undercore文档,Lo Dash文档(什么是LoDash?)

看起来其他答案提到使用debounce而不是throttle。我找到了一个解决方案,它允许您在确保最后一次调用的同时保持节流行为(保持函数调用的进行)。

https://gist.github.com/ayushv512/a2f963bface38f5e2f6f6bba39bba9b9#file-节流js

 const throttle = (func, limit) => {
  let lastFunc;
  let lastRan;
  return function() {
    const context = this;
    const args = arguments;
    if (!lastRan) {
      func.apply(context, args)
      lastRan = Date.now();
    } else {
      clearTimeout(lastFunc);
      lastFunc = setTimeout(function() {
          if ((Date.now() - lastRan) >= limit) {
            func.apply(context, args);
            lastRan = Date.now();
          }
       }, limit - (Date.now() - lastRan));
    }
  }
}

迟到了,但接受的答案是一个防反弹函数,而不是油门+我有一个更通用的油门函数,它可以作为正常或防反弹版本,以确保在延迟结束后触发最后一个调用。因此,如果你想,基本上可以将油门和反跳合并为一个

function throttle(f, delay = 0, ensure = false) {
  let lastCall = Number.NEGATIVE_INFINITY;
  let wait;
  let handle;
  return (...args) => {
    wait = lastCall + delay - Date.now();
    clearTimeout(handle);
    if (wait <= 0 || ensure) {
      handle = setTimeout(() => {
        f(...args);
        lastCall = Date.now();
      }, wait);
    }
  };
}

工作原理:

  • 它最重要的是一个简单的throttle函数,如果最后一次调用的时间比delay长,则可以调用它
  • 您可以设置一个标志CCD_ 4以使throttle函数确保最后一个调用将被调用;帧";
    • 例如,如果将函数限制为每秒1次调用,则意味着它只会在上次调用超过1秒时激发
  • 如果您在启用ensure标志的情况下调用throttle函数,而最后一次调用的时间不到1秒,例如600ms,则throttled函数只需设置一个超时值,以在400ms内调用该函数(wait = lastCall + delay - Date.now()-此处,如果lastCall = 0delay = 1000Date.now() = 600,则超时将发生在400中)
  • 否则,如果你想把它当作一个简单的节流函数,就不要设置CCD_;帧";将被忽略

我认为这是一个优雅的解决方案,可以为简单的油门功能添加更多功能。我用它在编辑器中移动东西,同时保持重画在一定的帧速率,但仍然确保本应在帧之间发生的移动仍然被应用

我保留了一个idle函数来处理这种类型的用户交互。这个想法是要求以规则的间隔调用一些函数(即,当在输入中按下某个键时);只要间隔过去而没有调用所述函数,就会触发单独的回调。这可能不是你想要的自动完成行为(你可能想在用户输入暂停之前开始搜索),但这是我过去使用过的一种方法。

不过,如果有人对此有更好的解决方案,我会洗耳恭听的!

是的,你说得对,它不适合自动完成表单。不过,我认为它适用于其他类型的东西。给出的示例是处理滚动事件。

相关内容

最新更新