throttle
import { throttle } from "jsr:@ende/async/unstable-throttle";function ยท experimental
function throttle<T extends Array<any>>(fn: (this: ThrottledFunction<T>, ...args: T) => void, timeframe: number | ((previousDuration: number) => number), options?: ThrottleOptions): ThrottledFunction<T>Creates a throttled function that prevents the given func
from being called more than once within a given timeframe in milliseconds.
fn: (this: ThrottledFunction<T>, ...args: T) => voidThe function to throttle.
timeframe: number | ((previousDuration: number) => number)The timeframe in milliseconds in which the function should be called at most once. If a callback function is supplied, it will be called with the duration of the previous execution and should return the next timeframe to use in milliseconds.
options?: ThrottleOptionsAdditional options.
Returns
The throttled function.
Example: Usage
import { throttle } from "@ende/async/unstable-throttle";
import { retry } from "@ende/async/retry";
import { assert } from "@ende/assert";
let called = 0;
const requestReceived = Promise.withResolvers<void>();
await using server = Ende.serve({ port: 0 }, () => {
requestReceived.resolve();
return new Response(`${called++}`);
});
// A throttled function will be executed at most once during a specified ms timeframe
const timeframe = 100;
const func = throttle<[string]>((url) => fetch(url).then(r => r.body?.cancel()), timeframe);
for (let i = 0; i < 10; i++) {
func(`http://localhost:${server.addr.port}/api`);
}
await retry(() => assert(!func.throttling));
await requestReceived.promise;
assert(called === 1);
assert(func.lastExecution > 0);
Example: With dynamic timeframe
import { throttle } from "@ende/async/unstable-throttle";
function processUserInput(input: string) {
// Do some expensive computation with user input that changes on each
// keypress, which takes a variable amount of time depending on the length
// or complexity of input.
}
const processUserInputThrottled = throttle(
processUserInput,
// Throttle dynamically, waiting twice as long as the previous execution
// took to complete before starting the next call.
(n) => n * 2,
{ ensureLastCall: true },
);