/** * Creates a function that samples calls at regular intervals and captures trailing calls. * - Drops calls that occur between sampling intervals * - Takes one call per sampling interval if available * - Captures the last call if no call was made during the interval * * @param fn The function to sample * @param sampleInterval How often to sample calls (in ms) * @returns The sampled function */ export function createSampler any>(fn: T, sampleInterval: number): T { let lastArgs: Parameters | null = null; let lastTime = 0; let timeout: NodeJS.Timeout | null = null; // Create a function with the same type as the input function const sampled = function (this: any, ...args: Parameters) { const now = Date.now(); lastArgs = args; // If we're within the sample interval, just store the args if (now - lastTime < sampleInterval) { // Set up trailing call if not already set if (!timeout) { timeout = setTimeout( () => { timeout = null; lastTime = Date.now(); if (lastArgs) { fn.apply(this, lastArgs); lastArgs = null; } }, sampleInterval - (now - lastTime), ); } return; } // If we're outside the interval, execute immediately lastTime = now; fn.apply(this, args); lastArgs = null; } as T; return sampled; }