git-watchtower 2.0.1 → 2.0.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/package.json +1 -1
- package/src/utils/async.js +37 -4
package/package.json
CHANGED
package/src/utils/async.js
CHANGED
|
@@ -175,6 +175,18 @@ function sleep(ms) {
|
|
|
175
175
|
|
|
176
176
|
/**
|
|
177
177
|
* Debounce a function - only execute after delay with no calls
|
|
178
|
+
*
|
|
179
|
+
* cancel() both clears the pending timer and sets an internal flag
|
|
180
|
+
* that the scheduled callback checks at the top. Without the flag,
|
|
181
|
+
* cancel() racing with a timer whose callback has already been
|
|
182
|
+
* dequeued (the timer fired, but the callback hadn't executed yet)
|
|
183
|
+
* was a no-op — clearTimeout can't recall a callback that libuv
|
|
184
|
+
* has already promoted — so fn would run anyway and write into
|
|
185
|
+
* state the caller had just asked to abandon.
|
|
186
|
+
*
|
|
187
|
+
* Calling debounced(...) re-arms: the cancelled flag resets so a new
|
|
188
|
+
* schedule is not pre-squelched by a prior cancel().
|
|
189
|
+
*
|
|
178
190
|
* @template {(...args: any[]) => void} T
|
|
179
191
|
* @param {T} fn - Function to debounce
|
|
180
192
|
* @param {number} delay - Delay in milliseconds
|
|
@@ -182,18 +194,22 @@ function sleep(ms) {
|
|
|
182
194
|
*/
|
|
183
195
|
function debounce(fn, delay) {
|
|
184
196
|
let timeoutId = null;
|
|
197
|
+
let cancelled = false;
|
|
185
198
|
|
|
186
199
|
const debounced = (...args) => {
|
|
187
200
|
if (timeoutId) {
|
|
188
201
|
clearTimeout(timeoutId);
|
|
189
202
|
}
|
|
203
|
+
cancelled = false;
|
|
190
204
|
timeoutId = setTimeout(() => {
|
|
191
|
-
fn(...args);
|
|
192
205
|
timeoutId = null;
|
|
206
|
+
if (cancelled) return;
|
|
207
|
+
fn(...args);
|
|
193
208
|
}, delay);
|
|
194
209
|
};
|
|
195
210
|
|
|
196
211
|
debounced.cancel = () => {
|
|
212
|
+
cancelled = true;
|
|
197
213
|
if (timeoutId) {
|
|
198
214
|
clearTimeout(timeoutId);
|
|
199
215
|
timeoutId = null;
|
|
@@ -206,17 +222,24 @@ function debounce(fn, delay) {
|
|
|
206
222
|
|
|
207
223
|
/**
|
|
208
224
|
* Throttle a function - execute at most once per interval
|
|
225
|
+
*
|
|
226
|
+
* Mirrors debounce() in returning a wrapped function with a `.cancel()`
|
|
227
|
+
* method. If a trailing call has been scheduled (throttle fires on the
|
|
228
|
+
* leading edge and coalesces further calls during the interval into a
|
|
229
|
+
* single trailing call), cancel() drops it. Wire cancel() into shutdown
|
|
230
|
+
* paths so a UI-event-driven throttle can't fire a deferred call after
|
|
231
|
+
* the target module has torn down and leave state partially written.
|
|
232
|
+
*
|
|
209
233
|
* @template {(...args: any[]) => void} T
|
|
210
234
|
* @param {T} fn - Function to throttle
|
|
211
235
|
* @param {number} interval - Minimum interval between calls in milliseconds
|
|
212
|
-
* @returns {T}
|
|
236
|
+
* @returns {T & { cancel: () => void }}
|
|
213
237
|
*/
|
|
214
238
|
function throttle(fn, interval) {
|
|
215
239
|
let lastCall = 0;
|
|
216
240
|
let timeoutId = null;
|
|
217
241
|
|
|
218
|
-
|
|
219
|
-
return (...args) => {
|
|
242
|
+
const throttled = (...args) => {
|
|
220
243
|
const now = Date.now();
|
|
221
244
|
const timeSinceLastCall = now - lastCall;
|
|
222
245
|
|
|
@@ -232,6 +255,16 @@ function throttle(fn, interval) {
|
|
|
232
255
|
}, interval - timeSinceLastCall);
|
|
233
256
|
}
|
|
234
257
|
};
|
|
258
|
+
|
|
259
|
+
throttled.cancel = () => {
|
|
260
|
+
if (timeoutId) {
|
|
261
|
+
clearTimeout(timeoutId);
|
|
262
|
+
timeoutId = null;
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
// @ts-ignore - TypeScript can't verify generic function augmentation
|
|
267
|
+
return throttled;
|
|
235
268
|
}
|
|
236
269
|
|
|
237
270
|
module.exports = {
|