@avatijs/debounce 0.1.1 โ 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
[](https://badge.fury.io/js/@avatijs%2Fdebounce)
|
4
|
+
[](https://www.typescriptlang.org/)
|
5
|
+
[](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
|
+
[](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
|
+
[](https://x.com/khaledsmq_)
|
154
|
+
[](https://www.linkedin.com/in/khaledsmq/)
|
155
|
+
[](https://medium.com/@khaled.smq)
|
156
|
+
[](https://github.com/KhaledSMQ)
|
157
|
+
[](https://github.com/KhaledSMQ/avati/stargazers)
|
158
|
+
[](https://github.com/KhaledSMQ)
|
241
159
|
|
242
|
-
|
160
|
+
</div>
|