【问题标题】:Rate limit function calls in TypescriptTypescript 中的速率限制函数调用
【发布时间】:2016-10-01 02:36:05
【问题描述】:

更新:我现在知道油门会丢弃多余的函数调用,所以它不是正确的工具。我仍然想要一种惯用的方式来处理队列中的所有项目,而不会太快或丢弃任何项目。


我正在编写一个节点应用程序,该应用程序会遇到具有速率限制的 API。我创建呼叫的速度比允许发送呼叫的速度快得多。我想消耗一个呼叫队列,但不要太快或放弃任何一个。我做了一个小打字测试来说明我的麻烦:

import * as _ from "lodash";

let start = new Date().getTime();

function doLog(s: string) {
  let elapsed = new Date().getTime() - start;
  console.log(`${s} ${elapsed}`);
}

let array = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
let throttled = _.throttle(doLog, 100);
array.forEach(s => throttled(s));

我希望看到的输出大致如下:

a 2
b 101
c 203
d 302
e 405
f 502
g 603
h 706
i 804
j 902

但我看到的是:

a 2
j 101

我做了一些奇怪的观察:

  • 在 100 毫秒节流时,数组的大小似乎无关紧要:我将打印数组中的第一项和最后一项,无论它有 2 个元素还是 20 个元素。
  • 在 1 毫秒的节流阀时,我从数组的前面打印 3-6 个元素,最后一个元素

【问题讨论】:

  • 是的,这不是节流的意思。见the documentation。您可以编写自己的类来执行您想要的行为...我认为 lodash 中没有任何东西可以处理。
  • 我已经做到了。我还阅读了文档中链接的 David Corbacho 的文章。文档说“受限制的函数带有一个取消延迟函数调用的取消方法和一个立即调用它们的刷新方法。” “延迟函数调用”这句话对我来说听起来确实像是在排队调用......但听起来我错了,这很好。我应该使用其他功能/实用程序吗?

标签: typescript lodash throttling


【解决方案1】:

如果您不关心 doLog() 在调用下一个之前是否安全“完成”,您可以使用 setTimeout

let array = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
array.forEach((s, i) => setTimeout(doLog, i*100, s));

Adam 很好地解释了为什么 throttle 在这种情况下不好。

【讨论】:

  • 啊,太简单了!我试过 setTimeout 但没有考虑动态增加延迟。
【解决方案2】:

如果在等待期间多次调用受限制的函数,则后续调用将被忽略。如果您需要处理数组中的每个项目,throttle() 可能不是您想要的。例如,它更适合防止 UI 中的过度更新。

您总是在输出中看到aj 的原因是前缘和后缘。整个数组的处理时间不到 100 毫秒,但由于前导和尾随默认为 true,因此您会看到这两个调用(对节流函数的第一次和最后一次调用)。

【讨论】:

  • 感谢您对前缘/后缘的澄清;这有助于理解输出。是否有惯用的解决方案(或库)以一定的速率处理数组中的每个项目?
  • 我确定有。为什么要限制数组处理,只是出于好奇?
  • 我多次调用一个 API,如果我走得太快,那个 API 会拒绝我。我远低于每日速率,但我很容易超过每秒速率。
【解决方案3】:

如果你愿意使用 RxJS,这个答案会让你相当地道地实现这一点:

https://stackoverflow.com/a/31855054/553003

【讨论】:

  • 不错的主意!...比其他解决方案更符合要求
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多