Skip to content

Commit aeeb2b6

Browse files
committed
feat: Added throttle utility functions
1 parent 446fec0 commit aeeb2b6

4 files changed

Lines changed: 57 additions & 0 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ const copied = await commonUtil.copyToClipboard("Hello, World!"); // true if suc
7575
const encoded = commonUtil.encodeBase64("Hello 한글!"); // Base64 encoded string
7676
const decoded = commonUtil.decodeBase64(encoded); // "Hello 한글!"
7777
const debouncedFn = commonUtil.debounce(() => console.log("Called!"), 300); // Debounced function
78+
const throttledFn = commonUtil.throttle(() => console.log("Throttled!"), 300); // Throttled function
7879

7980
// Search Query utilities
8081
const queryParams = searchQueryUtil.getAllQuery(); // { key: ["value1", "value2"], id: "123" }
@@ -160,6 +161,7 @@ const cleaned = clearNullProperties({ a: 1, b: null, c: 3 });
160161
- `encodeBase64(str: string, options?: { convertSpecialChars?: boolean }): string` - Encodes a string to Base64 format with optional special character handling
161162
- `decodeBase64(str: string, options?: { convertSpecialChars?: boolean }): string` - Decodes a Base64 string back to original text with optional special character handling
162163
- `debounce<T>(fn: T, delay?: number): (...args: Parameters<T>) => void` - Creates a debounced function that delays execution until after a specified delay (default 300ms) has passed since its last invocation
164+
- `throttle<T>(fn: T, limit?: number): (...args: Parameters<T>) => void` - Creates a throttled function that only executes at most once per specified time interval (default 300ms), ignoring subsequent calls within the limit
163165

164166
### SearchQueryUtil
165167

package/commonUtil/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ export { default as copyToClipboard } from "./copyToClipboard";
55
export { default as encodeBase64 } from "./encodeBase64";
66
export { default as decodeBase64 } from "./decodeBase64";
77
export { default as debounce } from "./debounce";
8+
export { default as throttle } from "./throttle";
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { afterEach, describe, expect, test, vi } from "vitest";
2+
import throttle from ".";
3+
4+
describe("throttle 유틸 함수 테스트", () => {
5+
afterEach(() => {
6+
vi.useRealTimers();
7+
vi.restoreAllMocks();
8+
});
9+
test("함수가 지정된 시간 (300ms) 간격으로만 실행되어야 한다.", () => {
10+
const fn = vi.fn();
11+
vi.useFakeTimers();
12+
const throttleFn = throttle(fn, 300);
13+
14+
throttleFn();
15+
expect(fn).toHaveBeenCalledTimes(1);
16+
17+
throttleFn();
18+
vi.advanceTimersByTime(299);
19+
throttleFn();
20+
expect(fn).toHaveBeenCalledTimes(1);
21+
22+
vi.advanceTimersByTime(1);
23+
throttleFn();
24+
expect(fn).toHaveBeenCalledTimes(2);
25+
});
26+
test("여러 번 호출했을 경우에는 지정된 시간 간격으로만 이벤트가 실행되어야 한다.", () => {
27+
const fn = vi.fn();
28+
vi.useFakeTimers();
29+
const throttled = throttle(fn, 300);
30+
31+
throttled({ name: "현우" });
32+
vi.advanceTimersByTime(100);
33+
throttled({ name: "승준" });
34+
vi.advanceTimersByTime(100);
35+
throttled({ name: "철수" });
36+
37+
vi.advanceTimersByTime(300);
38+
expect(fn).toHaveBeenCalledTimes(1);
39+
expect(fn).toHaveBeenNthCalledWith(1, { name: "현우" });
40+
});
41+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export default function throttle<T extends (...args: unknown[]) => void>(
2+
fn: T,
3+
limit: number = 300
4+
) {
5+
let isThrottled: boolean;
6+
return (...args: Parameters<T>) => {
7+
if (!isThrottled) {
8+
fn(...args);
9+
isThrottled = true;
10+
setTimeout(() => (isThrottled = false), limit);
11+
}
12+
};
13+
}

0 commit comments

Comments
 (0)