@superutils/promise 1.0.7 → 1.1.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.
- package/dist/index.d.ts +28 -12
- package/dist/index.js +77 -55
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -85,14 +85,17 @@ type DeferredAsyncDefaults = Pick<Required<DeferredAsyncOptions>, 'delayMs' | 'r
|
|
|
85
85
|
/** Options for `PromisE.deferred` and other related functions */
|
|
86
86
|
type DeferredAsyncOptions<ThisArg = unknown, DelayMs extends number = number> = {
|
|
87
87
|
/**
|
|
88
|
-
* Delay in milliseconds, used for `debounce` and `throttle` modes.
|
|
88
|
+
* Delay in milliseconds, used for `debounce` and `throttle` modes. Use `0` for sequential execution.
|
|
89
89
|
*
|
|
90
|
-
*
|
|
90
|
+
* Use `0` to disable debounce/throttle and execute all operations sequentially.
|
|
91
|
+
*
|
|
92
|
+
* Default: `100` (or what is set in `PromisE.deferred.defaults.delayMs`)
|
|
91
93
|
*/
|
|
94
|
+
delayMs?: 0 | PositiveNumber<DelayMs>;
|
|
92
95
|
/** Callback invoked whenever promise/function throws error */
|
|
93
96
|
onError?: (this: ThisArg, err: unknown) => ValueOrPromise<unknown>;
|
|
94
97
|
/**
|
|
95
|
-
* Whenever a promise/function is ignored when in
|
|
98
|
+
* Whenever a promise/function is ignored when in debounce/throttle mode, `onIgnored` wil be invoked.
|
|
96
99
|
* The promise/function will not be invoked, unless it's manually invoked using the `ignored` function.
|
|
97
100
|
* Use for debugging or logging purposes.
|
|
98
101
|
*/
|
|
@@ -118,13 +121,13 @@ type DeferredAsyncOptions<ThisArg = unknown, DelayMs extends number = number> =
|
|
|
118
121
|
thisArg?: ThisArg;
|
|
119
122
|
} & (({
|
|
120
123
|
/** Throttle duration in milliseconds */
|
|
121
|
-
delayMs
|
|
124
|
+
delayMs: PositiveNumber<DelayMs>;
|
|
122
125
|
throttle: true;
|
|
123
|
-
} &
|
|
126
|
+
} & Pick<ThrottleOptions, 'trailing'>) | ({
|
|
124
127
|
/** Debounce/deferred duration in milliseconds */
|
|
125
128
|
delayMs?: PositiveNumber<DelayMs>;
|
|
126
|
-
throttle?: false
|
|
127
|
-
} &
|
|
129
|
+
throttle?: false;
|
|
130
|
+
} & Pick<DeferredOptions, 'leading'>));
|
|
128
131
|
/** Determines what to do when deferred promise/function fails */
|
|
129
132
|
declare enum ResolveError {
|
|
130
133
|
/** Neither resolve nor reject the failed */
|
|
@@ -143,7 +146,7 @@ declare enum ResolveError {
|
|
|
143
146
|
declare enum ResolveIgnored {
|
|
144
147
|
/** Never resolve ignored promises. Caution: make sure this doesn't cause any memory leaks. */
|
|
145
148
|
NEVER = "NEVER",
|
|
146
|
-
/** (default) resolve with active promise result, the one that caused the current promise/callback to be ignored
|
|
149
|
+
/** (default) resolve with active promise result, the one that caused the current promise/callback to be ignored. */
|
|
147
150
|
WITH_LAST = "WITH_LAST",
|
|
148
151
|
/** resolve with `undefined` value */
|
|
149
152
|
WITH_UNDEFINED = "WITH_UNDEFINED"
|
|
@@ -172,7 +175,7 @@ type RetryOptions<T = unknown> = {
|
|
|
172
175
|
*/
|
|
173
176
|
retryDelay?: number;
|
|
174
177
|
/**
|
|
175
|
-
* Add a random delay between 0ms and `retryDelayJitterMax` to the `
|
|
178
|
+
* Add a random delay between 0ms and `retryDelayJitterMax` to the `retryDelay`.
|
|
176
179
|
* Default: `true`
|
|
177
180
|
*/
|
|
178
181
|
retryDelayJitter?: boolean;
|
|
@@ -220,7 +223,13 @@ declare class PromisEBase<T = unknown> extends Promise<T> implements IPromisE<T>
|
|
|
220
223
|
get rejected(): boolean;
|
|
221
224
|
/** Indicates if the promise has been resolved */
|
|
222
225
|
get resolved(): boolean;
|
|
223
|
-
/**
|
|
226
|
+
/**
|
|
227
|
+
* Get promise status code:
|
|
228
|
+
*
|
|
229
|
+
* - `0` = pending
|
|
230
|
+
* - `1` = resolved
|
|
231
|
+
* - `2` = rejected
|
|
232
|
+
*/
|
|
224
233
|
get state(): 0 | 1 | 2;
|
|
225
234
|
/** Resovle pending promise early. */
|
|
226
235
|
resolve: (value: T | PromiseLike<T>) => void;
|
|
@@ -348,7 +357,7 @@ type TimeoutOptions<Func extends string = 'all'> = {
|
|
|
348
357
|
* @example Explanation & example usage:
|
|
349
358
|
* ```typescript
|
|
350
359
|
* const example = throttle => {
|
|
351
|
-
* const df = PromisE.deferred(throttle)
|
|
360
|
+
* const df = PromisE.deferred({ delayMs: 100, throttle })
|
|
352
361
|
* df(() => PromisE.delay(5000)).then(console.log)
|
|
353
362
|
* df(() => PromisE.delay(500)).then(console.log)
|
|
354
363
|
* df(() => PromisE.delay(1000)).then(console.log)
|
|
@@ -374,8 +383,15 @@ type TimeoutOptions<Func extends string = 'all'> = {
|
|
|
374
383
|
declare function deferred<T, ThisArg = unknown, Delay extends number = number>(options?: DeferredAsyncOptions<ThisArg, Delay>): DeferredAsyncCallback;
|
|
375
384
|
declare namespace deferred {
|
|
376
385
|
var defaults: {
|
|
386
|
+
/**
|
|
387
|
+
* Default delay in milliseconds, used in `debounce` and `throttle` modes.
|
|
388
|
+
*
|
|
389
|
+
* Use `0` (or negative number) to disable debounce/throttle and execute all operations sequentially.
|
|
390
|
+
*/
|
|
377
391
|
delayMs: number;
|
|
392
|
+
/** Set the default error resolution behavior. {@link ResolveError} for all options. */
|
|
378
393
|
resolveError: ResolveError.REJECT;
|
|
394
|
+
/** Set the default ignored resolution behavior. See {@link ResolveIgnored} for all options. */
|
|
379
395
|
resolveIgnored: ResolveIgnored.WITH_LAST;
|
|
380
396
|
};
|
|
381
397
|
}
|
|
@@ -682,7 +698,7 @@ declare class PromisE<T = unknown> extends PromisEBase<T> {
|
|
|
682
698
|
* - `'linear'` uses a constant delay.
|
|
683
699
|
*
|
|
684
700
|
* Default: `'exponential'`
|
|
685
|
-
* @param options.
|
|
701
|
+
* @param options.retryDelay (optional) The base delay in milliseconds between retries.
|
|
686
702
|
*
|
|
687
703
|
* Default: `300`
|
|
688
704
|
* @param options.retryDelayJitter (optional) If true, adds a random jitter to the delay to prevent
|
package/dist/index.js
CHANGED
|
@@ -76,7 +76,13 @@ var _PromisEBase = class _PromisEBase extends Promise {
|
|
|
76
76
|
get resolved() {
|
|
77
77
|
return this._state === 1;
|
|
78
78
|
}
|
|
79
|
-
/**
|
|
79
|
+
/**
|
|
80
|
+
* Get promise status code:
|
|
81
|
+
*
|
|
82
|
+
* - `0` = pending
|
|
83
|
+
* - `1` = resolved
|
|
84
|
+
* - `2` = rejected
|
|
85
|
+
*/
|
|
80
86
|
get state() {
|
|
81
87
|
return this._state;
|
|
82
88
|
}
|
|
@@ -169,101 +175,117 @@ var ResolveIgnored = /* @__PURE__ */ ((ResolveIgnored2) => {
|
|
|
169
175
|
})(ResolveIgnored || {});
|
|
170
176
|
|
|
171
177
|
// src/deferred.ts
|
|
172
|
-
function deferred(options) {
|
|
173
|
-
|
|
174
|
-
|
|
178
|
+
function deferred(options = {}) {
|
|
179
|
+
options = objCopy(
|
|
180
|
+
deferred.defaults,
|
|
181
|
+
options,
|
|
182
|
+
[],
|
|
183
|
+
"empty"
|
|
184
|
+
);
|
|
175
185
|
let { onError, onIgnore, onResult } = options;
|
|
176
186
|
const {
|
|
177
|
-
delayMs,
|
|
187
|
+
delayMs = 0,
|
|
178
188
|
resolveError,
|
|
179
|
-
// by default reject on error
|
|
180
189
|
resolveIgnored,
|
|
181
190
|
thisArg,
|
|
182
191
|
throttle
|
|
183
192
|
} = options;
|
|
184
|
-
let
|
|
193
|
+
let prevQItem = null;
|
|
185
194
|
const queue = /* @__PURE__ */ new Map();
|
|
186
|
-
const
|
|
195
|
+
const isSequential = !isPositiveNumber(delayMs);
|
|
187
196
|
if (thisArg !== void 0) {
|
|
188
197
|
onError = onError == null ? void 0 : onError.bind(thisArg);
|
|
189
198
|
onIgnore = onIgnore == null ? void 0 : onIgnore.bind(thisArg);
|
|
190
199
|
onResult = onResult == null ? void 0 : onResult.bind(thisArg);
|
|
191
200
|
}
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
201
|
+
const handleRemaining = (currentId) => {
|
|
202
|
+
const _prevQItem = prevQItem;
|
|
203
|
+
prevQItem = null;
|
|
204
|
+
if (isSequential) {
|
|
195
205
|
queue.delete(currentId);
|
|
196
206
|
const [nextId, nextItem] = [...queue.entries()][0] || [];
|
|
197
|
-
return nextId && nextItem &&
|
|
207
|
+
return nextId && nextItem && handleItem(nextId, nextItem);
|
|
198
208
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
209
|
+
let items = [...queue.entries()];
|
|
210
|
+
if (throttle && options.trailing) {
|
|
211
|
+
items = items.slice(
|
|
212
|
+
0,
|
|
213
|
+
items.findIndex(([id]) => id === currentId)
|
|
214
|
+
);
|
|
215
|
+
} else if (!throttle && options.leading) {
|
|
216
|
+
items = items.slice(0, -1);
|
|
217
|
+
}
|
|
218
|
+
for (const [iId, iItem] of items) {
|
|
219
|
+
!iItem.completed && queue.delete(iId);
|
|
220
|
+
if (iItem === void 0 || iItem.started || iItem.completed)
|
|
221
|
+
continue;
|
|
222
|
+
iItem.completed = true;
|
|
223
|
+
onIgnore && fallbackIfFails2(onIgnore, [iItem.getPromise], 0);
|
|
206
224
|
switch (resolveIgnored) {
|
|
207
225
|
case "WITH_UNDEFINED" /* WITH_UNDEFINED */:
|
|
208
226
|
iItem.resolve(void 0);
|
|
209
227
|
break;
|
|
210
228
|
case "WITH_LAST" /* WITH_LAST */:
|
|
211
|
-
|
|
229
|
+
_prevQItem == null ? void 0 : _prevQItem.then(iItem.resolve, iItem.reject);
|
|
212
230
|
break;
|
|
213
231
|
case "NEVER" /* NEVER */:
|
|
214
232
|
break;
|
|
215
233
|
}
|
|
216
234
|
}
|
|
217
235
|
};
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
236
|
+
const executeItem = async (id, qItem) => {
|
|
237
|
+
if (!id || !(qItem == null ? void 0 : qItem.pending) || qItem.completed) return;
|
|
238
|
+
qItem.started = true;
|
|
239
|
+
prevQItem = qItem;
|
|
240
|
+
try {
|
|
241
|
+
const result = await PromisEBase_default.try(qItem.getPromise);
|
|
242
|
+
qItem.resolve(result);
|
|
243
|
+
onResult && fallbackIfFails2(onResult, [result], void 0);
|
|
244
|
+
} catch (err) {
|
|
245
|
+
onError && fallbackIfFails2(onError, [err], void 0);
|
|
246
|
+
switch (resolveError) {
|
|
247
|
+
case "REJECT" /* REJECT */:
|
|
248
|
+
qItem.reject(err);
|
|
249
|
+
// eslint-disable-next-line no-fallthrough
|
|
250
|
+
case "NEVER" /* NEVER */:
|
|
251
|
+
break;
|
|
252
|
+
case "RESOLVE_UNDEFINED" /* WITH_UNDEFINED */:
|
|
253
|
+
qItem.resolve(void 0);
|
|
254
|
+
break;
|
|
255
|
+
case "RESOLVE_ERROR" /* WITH_ERROR */:
|
|
256
|
+
qItem.resolve(err);
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
238
259
|
}
|
|
260
|
+
qItem.completed = true;
|
|
261
|
+
handleRemaining(id);
|
|
239
262
|
};
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
finalizeCb(true, id, qItem),
|
|
246
|
-
finalizeCb(false, id, qItem)
|
|
247
|
-
);
|
|
248
|
-
};
|
|
249
|
-
if (!gotDelay) return execute2;
|
|
250
|
-
const deferFn = throttle ? throttledCore : deferredCore;
|
|
251
|
-
return deferFn(execute2, delayMs, options);
|
|
252
|
-
})();
|
|
263
|
+
const handleItem = isSequential ? executeItem : (throttle ? throttledCore : deferredCore)(
|
|
264
|
+
executeItem,
|
|
265
|
+
delayMs,
|
|
266
|
+
options
|
|
267
|
+
);
|
|
253
268
|
const deferredFunc = (promise) => {
|
|
254
|
-
const id = Symbol("deferred-queue-item-id");
|
|
269
|
+
const id = /* @__PURE__ */ Symbol("deferred-queue-item-id");
|
|
255
270
|
const qItem = new PromisEBase_default();
|
|
256
271
|
qItem.getPromise = isFn2(promise) ? promise : () => promise;
|
|
257
272
|
qItem.started = false;
|
|
258
273
|
queue.set(id, qItem);
|
|
259
|
-
if (
|
|
274
|
+
if (!prevQItem || !isSequential) handleItem(id, qItem);
|
|
260
275
|
return qItem;
|
|
261
276
|
};
|
|
262
277
|
return deferredFunc;
|
|
263
278
|
}
|
|
264
279
|
deferred.defaults = {
|
|
280
|
+
/**
|
|
281
|
+
* Default delay in milliseconds, used in `debounce` and `throttle` modes.
|
|
282
|
+
*
|
|
283
|
+
* Use `0` (or negative number) to disable debounce/throttle and execute all operations sequentially.
|
|
284
|
+
*/
|
|
265
285
|
delayMs: 100,
|
|
286
|
+
/** Set the default error resolution behavior. {@link ResolveError} for all options. */
|
|
266
287
|
resolveError: "REJECT" /* REJECT */,
|
|
288
|
+
/** Set the default ignored resolution behavior. See {@link ResolveIgnored} for all options. */
|
|
267
289
|
resolveIgnored: "WITH_LAST" /* WITH_LAST */
|
|
268
290
|
};
|
|
269
291
|
var deferred_default = deferred;
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"url": "https://github.com/alien45/superutils/issues"
|
|
5
5
|
},
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@superutils/core": "^1.
|
|
7
|
+
"@superutils/core": "^1.1.1"
|
|
8
8
|
},
|
|
9
9
|
"description": "An extended Promise with extra features such as status tracking, deferred/throttled execution, timeout and retry mechanism.",
|
|
10
10
|
"files": [
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"main": "dist/index.js",
|
|
24
24
|
"name": "@superutils/promise",
|
|
25
25
|
"peerDpendencies": {
|
|
26
|
-
"@superutils/core": "^1.
|
|
26
|
+
"@superutils/core": "^1.1.1"
|
|
27
27
|
},
|
|
28
28
|
"publishConfig": {
|
|
29
29
|
"access": "public"
|
|
@@ -43,5 +43,5 @@
|
|
|
43
43
|
"sideEffects": false,
|
|
44
44
|
"type": "module",
|
|
45
45
|
"types": "dist/index.d.ts",
|
|
46
|
-
"version": "1.0
|
|
46
|
+
"version": "1.1.0"
|
|
47
47
|
}
|