Typescript 中的速率限制函数调用
Rate limit function calls in Typescript
更新:我现在知道 throttle 会减少过多的函数调用,所以它不是正确的工具。我仍然想要一种惯用的方式来处理队列中的所有项目,而不会太快或丢弃任何项目。
我正在编写一个节点应用程序,它会达到 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 个元素。
- 在 1ms 节流时,我从数组的前面打印 3-6 个元素,最后一个元素
如果一个受限函数在其等待期间被多次调用,后续调用将被忽略。如果您需要处理数组中的每个项目,throttle()
可能不是您想要的。例如,它更适合防止 UI 中的过度更新。
您总是在输出中看到 a
和 j
的原因是前缘和后缘。整个数组的处理时间不到 100 毫秒,但由于前导和尾随默认为 true,您会看到这两个调用(对节流函数的第一次和最后一次调用)。
如果您愿意使用 RxJS,这个答案可以让您相当地道地实现这一目标:
如果你不关心 doLog()
在调用下一个之前是否安全 "done",你可以使用 setTimeout
let array = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
array.forEach((s, i) => setTimeout(doLog, i*100, s));
Adam 很好地解释了为什么 throttle
在这种情况下不好。
更新:我现在知道 throttle 会减少过多的函数调用,所以它不是正确的工具。我仍然想要一种惯用的方式来处理队列中的所有项目,而不会太快或丢弃任何项目。
我正在编写一个节点应用程序,它会达到 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 个元素。
- 在 1ms 节流时,我从数组的前面打印 3-6 个元素,最后一个元素
如果一个受限函数在其等待期间被多次调用,后续调用将被忽略。如果您需要处理数组中的每个项目,throttle()
可能不是您想要的。例如,它更适合防止 UI 中的过度更新。
您总是在输出中看到 a
和 j
的原因是前缘和后缘。整个数组的处理时间不到 100 毫秒,但由于前导和尾随默认为 true,您会看到这两个调用(对节流函数的第一次和最后一次调用)。
如果您愿意使用 RxJS,这个答案可以让您相当地道地实现这一目标:
如果你不关心 doLog()
在调用下一个之前是否安全 "done",你可以使用 setTimeout
let array = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
array.forEach((s, i) => setTimeout(doLog, i*100, s));
Adam 很好地解释了为什么 throttle
在这种情况下不好。