@tanstack/pacer 0.1.0 → 0.3.0

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.
Files changed (74) hide show
  1. package/dist/cjs/async-debouncer.cjs +112 -63
  2. package/dist/cjs/async-debouncer.cjs.map +1 -1
  3. package/dist/cjs/async-debouncer.d.cts +66 -25
  4. package/dist/cjs/async-queuer.cjs +198 -124
  5. package/dist/cjs/async-queuer.cjs.map +1 -1
  6. package/dist/cjs/async-queuer.d.cts +91 -49
  7. package/dist/cjs/async-rate-limiter.cjs +83 -55
  8. package/dist/cjs/async-rate-limiter.cjs.map +1 -1
  9. package/dist/cjs/async-rate-limiter.d.cts +55 -28
  10. package/dist/cjs/async-throttler.cjs +121 -70
  11. package/dist/cjs/async-throttler.cjs.map +1 -1
  12. package/dist/cjs/async-throttler.d.cts +75 -25
  13. package/dist/cjs/debouncer.cjs +45 -23
  14. package/dist/cjs/debouncer.cjs.map +1 -1
  15. package/dist/cjs/debouncer.d.cts +27 -12
  16. package/dist/cjs/index.cjs +2 -0
  17. package/dist/cjs/index.cjs.map +1 -1
  18. package/dist/cjs/index.d.cts +2 -0
  19. package/dist/cjs/queuer.cjs +161 -101
  20. package/dist/cjs/queuer.cjs.map +1 -1
  21. package/dist/cjs/queuer.d.cts +80 -38
  22. package/dist/cjs/rate-limiter.cjs +52 -44
  23. package/dist/cjs/rate-limiter.cjs.map +1 -1
  24. package/dist/cjs/rate-limiter.d.cts +38 -46
  25. package/dist/cjs/throttler.cjs +57 -44
  26. package/dist/cjs/throttler.cjs.map +1 -1
  27. package/dist/cjs/throttler.d.cts +35 -23
  28. package/dist/cjs/types.d.cts +8 -0
  29. package/dist/cjs/utils.cjs +13 -0
  30. package/dist/cjs/utils.cjs.map +1 -0
  31. package/dist/cjs/utils.d.cts +1 -0
  32. package/dist/esm/async-debouncer.d.ts +66 -25
  33. package/dist/esm/async-debouncer.js +112 -63
  34. package/dist/esm/async-debouncer.js.map +1 -1
  35. package/dist/esm/async-queuer.d.ts +91 -49
  36. package/dist/esm/async-queuer.js +198 -124
  37. package/dist/esm/async-queuer.js.map +1 -1
  38. package/dist/esm/async-rate-limiter.d.ts +55 -28
  39. package/dist/esm/async-rate-limiter.js +83 -55
  40. package/dist/esm/async-rate-limiter.js.map +1 -1
  41. package/dist/esm/async-throttler.d.ts +75 -25
  42. package/dist/esm/async-throttler.js +121 -70
  43. package/dist/esm/async-throttler.js.map +1 -1
  44. package/dist/esm/debouncer.d.ts +27 -12
  45. package/dist/esm/debouncer.js +45 -23
  46. package/dist/esm/debouncer.js.map +1 -1
  47. package/dist/esm/index.d.ts +2 -0
  48. package/dist/esm/index.js +2 -0
  49. package/dist/esm/index.js.map +1 -1
  50. package/dist/esm/queuer.d.ts +80 -38
  51. package/dist/esm/queuer.js +161 -101
  52. package/dist/esm/queuer.js.map +1 -1
  53. package/dist/esm/rate-limiter.d.ts +38 -46
  54. package/dist/esm/rate-limiter.js +52 -44
  55. package/dist/esm/rate-limiter.js.map +1 -1
  56. package/dist/esm/throttler.d.ts +35 -23
  57. package/dist/esm/throttler.js +57 -44
  58. package/dist/esm/throttler.js.map +1 -1
  59. package/dist/esm/types.d.ts +8 -0
  60. package/dist/esm/utils.d.ts +1 -0
  61. package/dist/esm/utils.js +13 -0
  62. package/dist/esm/utils.js.map +1 -0
  63. package/package.json +8 -1
  64. package/src/async-debouncer.ts +157 -88
  65. package/src/async-queuer.ts +266 -148
  66. package/src/async-rate-limiter.ts +123 -83
  67. package/src/async-throttler.ts +173 -89
  68. package/src/debouncer.ts +71 -42
  69. package/src/index.ts +2 -0
  70. package/src/queuer.ts +219 -114
  71. package/src/rate-limiter.ts +74 -88
  72. package/src/throttler.ts +83 -65
  73. package/src/types.ts +9 -0
  74. package/src/utils.ts +13 -0
package/src/debouncer.ts CHANGED
@@ -1,7 +1,9 @@
1
+ import type { AnyFunction } from './types'
2
+
1
3
  /**
2
4
  * Options for configuring a debounced function
3
5
  */
4
- export interface DebouncerOptions {
6
+ export interface DebouncerOptions<TFn extends AnyFunction> {
5
7
  /**
6
8
  * Whether the debouncer is enabled. When disabled, maybeExecute will not trigger any executions.
7
9
  * Defaults to true.
@@ -9,9 +11,14 @@ export interface DebouncerOptions {
9
11
  enabled?: boolean
10
12
  /**
11
13
  * Whether to execute on the leading edge of the timeout.
14
+ * The first call will execute immediately and the rest will wait the delay.
12
15
  * Defaults to false.
13
16
  */
14
17
  leading?: boolean
18
+ /**
19
+ * Callback function that is called after the function is executed
20
+ */
21
+ onExecute?: (debouncer: Debouncer<TFn>) => void
15
22
  /**
16
23
  * Whether to execute on the trailing edge of the timeout.
17
24
  * Defaults to true.
@@ -24,9 +31,10 @@ export interface DebouncerOptions {
24
31
  wait: number
25
32
  }
26
33
 
27
- const defaultOptions: Required<DebouncerOptions> = {
34
+ const defaultOptions: Required<DebouncerOptions<any>> = {
28
35
  enabled: true,
29
36
  leading: false,
37
+ onExecute: () => {},
30
38
  trailing: true,
31
39
  wait: 0,
32
40
  }
@@ -54,20 +62,18 @@ const defaultOptions: Required<DebouncerOptions> = {
54
62
  * });
55
63
  * ```
56
64
  */
57
- export class Debouncer<
58
- TFn extends (...args: Array<any>) => any,
59
- TArgs extends Parameters<TFn>,
60
- > {
61
- private canLeadingExecute = true
62
- private executionCount = 0
63
- private options: Required<DebouncerOptions>
64
- private timeoutId: NodeJS.Timeout | undefined
65
+ export class Debouncer<TFn extends AnyFunction> {
66
+ private _canLeadingExecute = true
67
+ private _executionCount = 0
68
+ private _isPending = false
69
+ private _options: Required<DebouncerOptions<TFn>>
70
+ private _timeoutId: NodeJS.Timeout | undefined
65
71
 
66
72
  constructor(
67
73
  private fn: TFn,
68
- initialOptions: DebouncerOptions,
74
+ initialOptions: DebouncerOptions<TFn>,
69
75
  ) {
70
- this.options = {
76
+ this._options = {
71
77
  ...defaultOptions,
72
78
  ...initialOptions,
73
79
  }
@@ -77,62 +83,85 @@ export class Debouncer<
77
83
  * Updates the debouncer options
78
84
  * Returns the new options state
79
85
  */
80
- setOptions(
81
- newOptions: Partial<DebouncerOptions>,
82
- ): Required<DebouncerOptions> {
83
- this.options = {
84
- ...this.options,
85
- ...newOptions,
86
+ setOptions(newOptions: Partial<DebouncerOptions<TFn>>): void {
87
+ this._options = { ...this._options, ...newOptions }
88
+
89
+ // End the pending state if the debouncer is disabled
90
+ if (!this._options.enabled) {
91
+ this._isPending = false
86
92
  }
87
- return this.options
88
93
  }
89
94
 
90
95
  /**
91
- * Returns the number of times the function has been executed
96
+ * Returns the current debouncer options
92
97
  */
93
- getExecutionCount(): number {
94
- return this.executionCount
98
+ getOptions(): Required<DebouncerOptions<TFn>> {
99
+ return this._options
95
100
  }
96
101
 
97
102
  /**
98
103
  * Attempts to execute the debounced function
99
104
  * If a call is already in progress, it will be queued
100
105
  */
101
- maybeExecute(...args: TArgs): void {
106
+ maybeExecute(...args: Parameters<TFn>): void {
107
+ let _didLeadingExecute = false
108
+
102
109
  // Handle leading execution
103
- if (this.options.leading && this.canLeadingExecute) {
110
+ if (this._options.leading && this._canLeadingExecute) {
111
+ this._canLeadingExecute = false
112
+ _didLeadingExecute = true
104
113
  this.executeFunction(...args)
105
- this.canLeadingExecute = false
114
+ }
115
+
116
+ // Start pending state to indicate that the debouncer is waiting for the trailing edge
117
+ if (this._options.trailing) {
118
+ this._isPending = true
106
119
  }
107
120
 
108
121
  // Clear any existing timeout
109
- if (this.timeoutId) clearTimeout(this.timeoutId)
122
+ if (this._timeoutId) clearTimeout(this._timeoutId)
110
123
 
111
- // Set new timeout that will reset canLeadingExecute
112
- this.timeoutId = setTimeout(() => {
113
- this.canLeadingExecute = true
114
- // Execute trailing only if enabled
115
- if (this.options.trailing) {
124
+ // Set new timeout that will reset canLeadingExecute and execute trailing only if enabled and did not execute leading
125
+ this._timeoutId = setTimeout(() => {
126
+ this._canLeadingExecute = true
127
+ if (this._options.trailing && !_didLeadingExecute) {
116
128
  this.executeFunction(...args)
117
129
  }
118
- }, this.options.wait)
130
+ }, this._options.wait)
119
131
  }
120
132
 
121
- private executeFunction(...args: TArgs): void {
122
- if (!this.options.enabled) return
123
- this.executionCount++
124
- this.fn(...args)
133
+ private executeFunction(...args: Parameters<TFn>): void {
134
+ if (!this._options.enabled) return undefined
135
+ this.fn(...args) // EXECUTE!
136
+ this._isPending = false
137
+ this._executionCount++
138
+ this._options.onExecute(this)
125
139
  }
126
140
 
127
141
  /**
128
142
  * Cancels any pending execution
129
143
  */
130
144
  cancel(): void {
131
- if (this.timeoutId) {
132
- clearTimeout(this.timeoutId)
133
- this.canLeadingExecute = true
145
+ if (this._timeoutId) {
146
+ clearTimeout(this._timeoutId)
147
+ this._canLeadingExecute = true
148
+ this._isPending = false
134
149
  }
135
150
  }
151
+
152
+ /**
153
+ * Returns the number of times the function has been executed
154
+ */
155
+ getExecutionCount(): number {
156
+ return this._executionCount
157
+ }
158
+
159
+ /**
160
+ * Returns `true` if debouncing
161
+ */
162
+ getIsPending(): boolean {
163
+ return this._options.enabled && this._isPending
164
+ }
136
165
  }
137
166
 
138
167
  /**
@@ -155,10 +184,10 @@ export class Debouncer<
155
184
  * inputElement.addEventListener('input', debounced);
156
185
  * ```
157
186
  */
158
- export function debounce<TFn extends (...args: Array<any>) => any>(
187
+ export function debounce<TFn extends AnyFunction>(
159
188
  fn: TFn,
160
- initialOptions: Omit<DebouncerOptions, 'enabled'>,
161
- ) {
189
+ initialOptions: Omit<DebouncerOptions<TFn>, 'enabled'>,
190
+ ): (...args: Parameters<TFn>) => void {
162
191
  const debouncer = new Debouncer(fn, initialOptions)
163
192
  return debouncer.maybeExecute.bind(debouncer)
164
193
  }
package/src/index.ts CHANGED
@@ -7,3 +7,5 @@ export * from './debouncer'
7
7
  export * from './queuer'
8
8
  export * from './rate-limiter'
9
9
  export * from './throttler'
10
+ export * from './types'
11
+ export * from './utils'