Skip to content

Commit

Permalink
feat: throttle function (#483)
Browse files Browse the repository at this point in the history
  • Loading branch information
legendhimself committed Oct 8, 2022
1 parent 5cc9a2c commit 541891a
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 0 deletions.
5 changes: 5 additions & 0 deletions packages/utilities/package.json
Expand Up @@ -261,6 +261,11 @@
"import": "./dist/lib/splitText.mjs",
"require": "./dist/lib/splitText.js"
},
"./throttle": {
"types": "./dist/lib/throttle.d.ts",
"import": "./dist/lib/throttle.mjs",
"require": "./dist/lib/throttle.js"
},
"./toTitleCase": {
"types": "./dist/lib/toTitleCase.d.ts",
"import": "./dist/lib/toTitleCase.mjs",
Expand Down
1 change: 1 addition & 0 deletions packages/utilities/src/index.ts
Expand Up @@ -37,6 +37,7 @@ export * from './lib/regExpEsc';
export * from './lib/roundNumber';
export { AbortError, sleep, sleepSync, type SleepOptions } from './lib/sleep';
export * from './lib/splitText';
export { throttle, type ThrottleFn } from './lib/throttle';
export { toTitleCase, type ToTitleCaseOptions } from './lib/toTitleCase';
export * from './lib/tryParseJSON';
export * from './lib/tryParseURL';
Expand Down
33 changes: 33 additions & 0 deletions packages/utilities/src/lib/throttle.ts
@@ -0,0 +1,33 @@
export type ThrottleFn<T extends (...args: any[]) => any> = T & { flush: () => void };

/**
* Creates a throttled function that only invokes `func` at most once per
* every `wait` milliseconds. The throttled function comes with a `flush` method to
* reset the last time the throttled function was invoked.
*
* @param func The function to throttle.
* @param wait The number of milliseconds to throttle invocations to.
*
* @returns Returns the new throttled function.
*/
export function throttle<T extends (...args: any[]) => any>(func: T, wait: number): ThrottleFn<T> {
let prev = 0;
let prevValue: ReturnType<T>;

return Object.assign(
(...args: Parameters<T>) => {
const now = Date.now();
if (now - prev > wait) {
prev = now;
return (prevValue = func(...args));
}

return prevValue;
},
{
flush() {
prev = 0;
}
}
) as ThrottleFn<T>;
}
26 changes: 26 additions & 0 deletions packages/utilities/tests/throttle.test.ts
@@ -0,0 +1,26 @@
import { throttle, sleep } from '../src';

describe('throttle', () => {
test('GIVEN number callback THEN returns the same output until the delay', async () => {
const callback = vi.fn((num: number) => num);

const throttleFunc = throttle(callback, 50);
const now = Date.now();
expect(throttleFunc(now)).toEqual(now);
expect(throttleFunc(100)).toEqual(now);
expect(callback).toHaveBeenCalledOnce();
await sleep(100);
expect(throttleFunc(250)).toEqual(250);
});

test('GIVEN number callback THEN returns the new output when flush', () => {
const callback = vi.fn((num: number) => num);

const throttleFunc = throttle(callback, 100);
const now = Date.now();
expect(throttleFunc(now)).toEqual(now);
throttleFunc.flush();
expect(throttleFunc(100)).toEqual(100);
expect(callback).toHaveBeenCalledTimes(2);
});
});

0 comments on commit 541891a

Please sign in to comment.