@avatijs/debounce 0.1.1 โ 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +135 -217
- package/dist/cjs/index.js +368 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.min.js +7 -0
- package/dist/cjs/index.min.js.map +1 -0
- package/dist/esm/index.js +353 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.min.js +7 -0
- package/dist/esm/index.min.js.map +1 -0
- package/dist/types/debouce.d.ts +1 -0
- package/dist/types/debouce.d.ts.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/umd/index.js +378 -2
- package/dist/umd/index.js.map +1 -1
- package/dist/umd/index.min.js +8 -0
- package/dist/umd/index.min.js.map +1 -0
- package/package.json +12 -5
- package/dist/debouce.d.ts +0 -72
- package/dist/index.d.ts +0 -1
package/README.md
CHANGED
@@ -1,242 +1,160 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
-
|
16
|
-
|
17
|
-
|
1
|
+
# TypeScript Debounce
|
2
|
+
|
3
|
+
[![npm version](https://badge.fury.io/js/@avatijs%2Fdebounce.svg)](https://badge.fury.io/js/@avatijs%2Fdebounce)
|
4
|
+
[![TypeScript](https://img.shields.io/badge/TypeScript-5.0-blue.svg)](https://www.typescriptlang.org/)
|
5
|
+
[![License](https://img.shields.io/npm/l/@avatijs%2Fdebounce.svg)](https://github.com/KhaledSMQ/avati/blob/master/LICENSE)
|
6
|
+
|
7
|
+
## Introduction
|
8
|
+
|
9
|
+
TypeScript Debounce is an elegant, robust debounce utility that brings the power of controlled function execution to your TypeScript applications. It provides a clean, type-safe API for managing function call rates, preventing resource overuse, and improving application performance.
|
10
|
+
|
11
|
+
### ๐ Why Another Debounce Library?
|
12
|
+
|
13
|
+
While there are many debounce implementations available, this library stands out by offering:
|
14
|
+
|
15
|
+
- **Full TypeScript Support**: Built from the ground up with TypeScript, providing complete type safety and excellent IDE integration
|
16
|
+
- **Promise-Based API**: Modern async/await support with proper error handling
|
17
|
+
- **Configurable Execution**: Control both leading and trailing edge execution
|
18
|
+
- **Resource Management**: Built-in cleanup and cancellation support
|
19
|
+
- **Debug Support**: Comprehensive logging for development troubleshooting
|
20
|
+
- **Maximum Wait Time**: Guarantee execution for long-running debounce periods
|
21
|
+
- **Zero Dependencies**: Lightweight and self-contained
|
22
|
+
|
23
|
+
## ๐ฏ When You Need This
|
24
|
+
|
25
|
+
Debouncing is crucial in many common development scenarios:
|
26
|
+
|
27
|
+
1. **Search Input Handling**
|
28
|
+
```typescript
|
29
|
+
// Without debounce - Makes API call on every keystroke
|
30
|
+
searchInput.addEventListener('input', async (e) => {
|
31
|
+
const results = await searchAPI(e.target.value); // ๐ด Excessive API calls
|
32
|
+
});
|
33
|
+
|
34
|
+
// With debounce - Waits for user to stop typing
|
35
|
+
const debouncedSearch = debounce(async (value: string) => {
|
36
|
+
const results = await searchAPI(value);
|
37
|
+
}, { wait: 300 }); // โ
Single API call after typing stops
|
38
|
+
```
|
39
|
+
|
40
|
+
2. **Window Resize Handling**
|
41
|
+
```typescript
|
42
|
+
// Without debounce - Recalculates layout on every resize event
|
43
|
+
window.addEventListener('resize', () => {
|
44
|
+
recalculateLayout(); // ๐ด Performance bottleneck
|
45
|
+
});
|
46
|
+
|
47
|
+
// With debounce - Controlled recalculation
|
48
|
+
const debouncedResize = debounce(() => {
|
49
|
+
recalculateLayout();
|
50
|
+
}, { wait: 150 }); // โ
Smooth performance
|
51
|
+
```
|
52
|
+
|
53
|
+
3. **Form Validation**
|
54
|
+
```typescript
|
55
|
+
// Without debounce - Validates on every change
|
56
|
+
input.addEventListener('input', async (e) => {
|
57
|
+
await validateField(e.target.value); // ๐ด Excessive validation
|
58
|
+
});
|
59
|
+
|
60
|
+
// With debounce - Validates after user stops typing
|
61
|
+
const debouncedValidate = debounce(async (value: string) => {
|
62
|
+
await validateField(value);
|
63
|
+
}, { wait: 400 }); // โ
Efficient validation
|
64
|
+
```
|
65
|
+
|
66
|
+
4. **Real-time Saving**
|
67
|
+
```typescript
|
68
|
+
// Without debounce - Saves on every change
|
69
|
+
editor.on('change', async (content) => {
|
70
|
+
await saveContent(content); // ๐ด Too many save operations
|
71
|
+
});
|
72
|
+
|
73
|
+
// With debounce - Intelligently batches saves
|
74
|
+
const debouncedSave = debounce(async (content: string) => {
|
75
|
+
await saveContent(content);
|
76
|
+
}, { wait: 1000 }); // โ
Optimized saving
|
77
|
+
```
|
78
|
+
|
79
|
+
## ๐ Installation
|
18
80
|
|
19
81
|
```bash
|
20
|
-
npm install
|
82
|
+
npm install typescript-debounce
|
83
|
+
# or
|
84
|
+
yarn add typescript-debounce
|
85
|
+
# or
|
86
|
+
pnpm add typescript-debounce
|
21
87
|
```
|
22
88
|
|
23
|
-
##
|
89
|
+
## ๐ Quick Start
|
24
90
|
|
25
91
|
```typescript
|
26
|
-
import { debounce } from '@
|
27
|
-
|
28
|
-
//
|
29
|
-
const debouncedFn = debounce(async (
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
//
|
34
|
-
|
35
|
-
|
36
|
-
//
|
37
|
-
|
38
|
-
|
39
|
-
debug: true
|
92
|
+
import { debounce } from '@avatijs/debounce';
|
93
|
+
|
94
|
+
// Create a debounced function
|
95
|
+
const debouncedFn = debounce(async (value: string) => {
|
96
|
+
const result = await api.search(value);
|
97
|
+
updateUI(result);
|
98
|
+
}, {
|
99
|
+
wait: 300, // Wait 300ms after last call
|
100
|
+
leading: false, // Don't execute on leading edge
|
101
|
+
trailing: true, // Execute on trailing edge
|
102
|
+
maxWait: 1000, // Maximum time to wait
|
103
|
+
debug: true, // Enable debug logging
|
104
|
+
onError: console.error // Error handling
|
40
105
|
});
|
41
106
|
|
42
|
-
//
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
});
|
48
|
-
|
49
|
-
// Cleanup when done
|
50
|
-
debouncedFn.cleanup();
|
51
|
-
```
|
52
|
-
|
53
|
-
## API Reference
|
54
|
-
|
55
|
-
### `debounce<T>(func: T, options?: DebounceOptions): DebouncedFunction<T>`
|
56
|
-
|
57
|
-
Creates a debounced version of the provided function.
|
58
|
-
|
59
|
-
#### Parameters
|
60
|
-
|
61
|
-
##### `func: T`
|
62
|
-
The function to debounce. Can be synchronous or asynchronous.
|
63
|
-
|
64
|
-
##### `options: DebounceOptions`
|
65
|
-
Configuration options for the debounced function.
|
66
|
-
|
67
|
-
```typescript
|
68
|
-
interface DebounceOptions {
|
69
|
-
readonly wait?: number; // Delay in milliseconds (default: 0)
|
70
|
-
readonly leading?: boolean; // Execute on leading edge (default: false)
|
71
|
-
readonly trailing?: boolean; // Execute on trailing edge (default: true)
|
72
|
-
readonly maxWait?: number; // Maximum time to wait
|
73
|
-
readonly debug?: boolean; // Enable debug logging (default: false)
|
74
|
-
readonly signal?: AbortSignal; // AbortController signal
|
75
|
-
}
|
76
|
-
```
|
77
|
-
|
78
|
-
#### Returns
|
79
|
-
|
80
|
-
Returns a debounced function with the following interface:
|
81
|
-
|
82
|
-
```typescript
|
83
|
-
interface DebouncedFunction<T> {
|
84
|
-
(...args: Parameters<T>): Promise<Awaited<ReturnType<T>>>;
|
85
|
-
readonly cancel: () => void;
|
86
|
-
readonly flush: (...args: Parameters<T>) => Promise<Awaited<ReturnType<T>>>;
|
87
|
-
readonly pending: () => boolean;
|
88
|
-
readonly cleanup: () => void;
|
107
|
+
// Use the debounced function
|
108
|
+
try {
|
109
|
+
await debouncedFn('search term');
|
110
|
+
} catch (error) {
|
111
|
+
handleError(error);
|
89
112
|
}
|
90
113
|
```
|
91
114
|
|
92
|
-
##
|
93
|
-
|
94
|
-
### Leading Edge Execution
|
95
|
-
|
96
|
-
```typescript
|
97
|
-
const leadingDebounce = debounce(
|
98
|
-
(value: string) => console.log(value),
|
99
|
-
{
|
100
|
-
wait: 1000,
|
101
|
-
leading: true,
|
102
|
-
trailing: false
|
103
|
-
}
|
104
|
-
);
|
105
|
-
|
106
|
-
// Executes immediately, then ignores calls for 1000ms
|
107
|
-
leadingDebounce("First");
|
108
|
-
leadingDebounce("Second"); // Ignored
|
109
|
-
leadingDebounce("Third"); // Ignored
|
110
|
-
```
|
111
|
-
|
112
|
-
### Maximum Wait Time
|
113
|
-
|
114
|
-
```typescript
|
115
|
-
const maxWaitDebounce = debounce(
|
116
|
-
(value: string) => console.log(value),
|
117
|
-
{
|
118
|
-
wait: 1000,
|
119
|
-
maxWait: 5000
|
120
|
-
}
|
121
|
-
);
|
122
|
-
|
123
|
-
// Will execute after 5000ms maximum, even if called continuously
|
124
|
-
const interval = setInterval(() => maxWaitDebounce("test"), 100);
|
125
|
-
```
|
126
|
-
|
127
|
-
### With AbortController
|
128
|
-
|
129
|
-
```typescript
|
130
|
-
const controller = new AbortController();
|
131
|
-
|
132
|
-
const abortableDebounce = debounce(
|
133
|
-
async (value: string) => {
|
134
|
-
await someAsyncOperation(value);
|
135
|
-
},
|
136
|
-
{
|
137
|
-
wait: 1000,
|
138
|
-
signal: controller.signal
|
139
|
-
}
|
140
|
-
);
|
141
|
-
|
142
|
-
// Later, abort all pending operations
|
143
|
-
controller.abort();
|
144
|
-
```
|
145
|
-
|
146
|
-
### Debug Mode
|
147
|
-
|
148
|
-
```typescript
|
149
|
-
const debugDebounce = debounce(
|
150
|
-
(value: string) => console.log(value),
|
151
|
-
{
|
152
|
-
wait: 1000,
|
153
|
-
debug: true
|
154
|
-
}
|
155
|
-
);
|
156
|
-
|
157
|
-
// Will log detailed information about internal state
|
158
|
-
debugDebounce("test");
|
159
|
-
```
|
160
|
-
|
161
|
-
### Handling Return Values
|
162
|
-
|
163
|
-
```typescript
|
164
|
-
const asyncDebounce = debounce(
|
165
|
-
async (x: number): Promise<number> => {
|
166
|
-
await delay(100);
|
167
|
-
return x * 2;
|
168
|
-
},
|
169
|
-
{ wait: 1000 }
|
170
|
-
);
|
171
|
-
|
172
|
-
// Get the result
|
173
|
-
const result = await asyncDebounce(5);
|
174
|
-
console.log(result); // 10
|
175
|
-
```
|
176
|
-
|
177
|
-
### Cleanup
|
178
|
-
|
179
|
-
```typescript
|
180
|
-
const debouncedFn = debounce((x: number) => x * 2, { wait: 1000 });
|
181
|
-
|
182
|
-
// Use the function
|
183
|
-
debouncedFn(5);
|
184
|
-
|
185
|
-
// Clean up when done
|
186
|
-
debouncedFn.cleanup();
|
187
|
-
```
|
188
|
-
|
189
|
-
## Best Practices
|
190
|
-
|
191
|
-
1. **Always Clean Up**: Call `cleanup()` when you're done with the debounced function to prevent memory leaks:
|
115
|
+
## Features
|
192
116
|
|
193
|
-
|
194
|
-
|
117
|
+
- **Type Safety**: Full TypeScript support with intelligent type inference
|
118
|
+
- **Promise Support**: Built-in handling of async functions
|
119
|
+
- **Cancellation**: Support for AbortController and manual cancellation
|
120
|
+
- **Maximum Wait**: Configure maximum delay before forced execution
|
121
|
+
- **Edge Control**: Configure execution on leading and/or trailing edge
|
122
|
+
- **Debug Mode**: Comprehensive logging for development
|
123
|
+
- **Error Handling**: Robust error handling with custom callbacks
|
124
|
+
- **Resource Management**: Automatic cleanup of resources
|
125
|
+
- **Memory Efficient**: Proper cleanup and memory management
|
195
126
|
|
196
|
-
|
197
|
-
debouncedFn.cleanup();
|
198
|
-
```
|
127
|
+
## Demo
|
199
128
|
|
200
|
-
|
129
|
+
Checkout the [Demo](https://codepen.io/khaledsmq/pen/wvVVYYe) to see TypeScript Debounce in action.
|
201
130
|
|
202
|
-
|
203
|
-
const debouncedFn = debounce(async () => {
|
204
|
-
try {
|
205
|
-
await debouncedOperation();
|
206
|
-
} catch (error) {
|
207
|
-
// Handle error
|
208
|
-
}
|
209
|
-
});
|
210
|
-
```
|
131
|
+
## Changelog
|
211
132
|
|
212
|
-
|
133
|
+
Please see [CHANGELOG](./CHANGELOG.md) for more information what has changed recently.
|
213
134
|
|
214
|
-
|
215
|
-
interface MyFuncParams {
|
216
|
-
id: number;
|
217
|
-
name: string;
|
218
|
-
}
|
135
|
+
## Contributing
|
219
136
|
|
220
|
-
|
221
|
-
(params: MyFuncParams) => console.log(params),
|
222
|
-
{ wait: 1000 }
|
223
|
-
);
|
137
|
+
I welcome contributions from developers of all experience levels. If you have an idea, found a bug, or want to improve something, I encourage you to get involved!
|
224
138
|
|
225
|
-
|
226
|
-
|
227
|
-
|
139
|
+
### How to Contribute
|
140
|
+
1. Read [Contributing Guide](https://github.com/KhaledSMQ/avati/blob/master/Contributing.md) for details on how to get started.
|
141
|
+
2. Fork the repository and make your changes.
|
142
|
+
3. Submit a pull request, and weโll review it as soon as possible.
|
228
143
|
|
229
|
-
##
|
144
|
+
## License
|
230
145
|
|
231
|
-
|
232
|
-
2. **Shared State**: Be careful with shared state in debounced functions.
|
233
|
-
3. **Error Handling**: Always handle potential errors in async operations.
|
234
|
-
4. **Maximum Wait Time**: Setting `maxWait` less than `wait` will throw an error.
|
146
|
+
[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/KhaledSMQ/avati/blob/master/LICENSE)
|
235
147
|
|
236
|
-
|
148
|
+
Avati is open-source and distributed under the [MIT License](https://github.com/KhaledSMQ/avati/blob/master/LICENSE).
|
237
149
|
|
238
|
-
|
150
|
+
---
|
151
|
+
<div align="center">
|
239
152
|
|
240
|
-
|
153
|
+
[![Follow on Twitter](https://img.shields.io/twitter/follow/KhaledSMQ.svg?style=social)](https://x.com/khaledsmq_)
|
154
|
+
[![Follow on LinkedIn](https://img.shields.io/badge/LinkedIn-Connect-blue.svg)](https://www.linkedin.com/in/khaledsmq/)
|
155
|
+
[![Follow on Medium](https://img.shields.io/badge/Medium-Follow-black.svg)](https://medium.com/@khaled.smq)
|
156
|
+
[![Made with โค๏ธ](https://img.shields.io/badge/Made%20with-โค๏ธ-red.svg)](https://github.com/KhaledSMQ)
|
157
|
+
[![Star on GitHub](https://img.shields.io/github/stars/KhaledSMQ/avati.svg?style=social)](https://github.com/KhaledSMQ/avati/stargazers)
|
158
|
+
[![Follow on GitHub](https://img.shields.io/github/followers/KhaledSMQ.svg?style=social&label=Follow)](https://github.com/KhaledSMQ)
|
241
159
|
|
242
|
-
|
160
|
+
</div>
|