@superutils/promise 1.0.9 → 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 +26 -14
- package/dist/index.js +70 -53
- 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,17 +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
129
|
throttle?: false;
|
|
127
|
-
} &
|
|
128
|
-
/** Sequential execution. All promises will be executed sequentially making sure there is no overlap. */
|
|
129
|
-
delayMs: 0;
|
|
130
|
-
throttle?: false;
|
|
131
|
-
});
|
|
130
|
+
} & Pick<DeferredOptions, 'leading'>));
|
|
132
131
|
/** Determines what to do when deferred promise/function fails */
|
|
133
132
|
declare enum ResolveError {
|
|
134
133
|
/** Neither resolve nor reject the failed */
|
|
@@ -176,7 +175,7 @@ type RetryOptions<T = unknown> = {
|
|
|
176
175
|
*/
|
|
177
176
|
retryDelay?: number;
|
|
178
177
|
/**
|
|
179
|
-
* Add a random delay between 0ms and `retryDelayJitterMax` to the `
|
|
178
|
+
* Add a random delay between 0ms and `retryDelayJitterMax` to the `retryDelay`.
|
|
180
179
|
* Default: `true`
|
|
181
180
|
*/
|
|
182
181
|
retryDelayJitter?: boolean;
|
|
@@ -224,7 +223,13 @@ declare class PromisEBase<T = unknown> extends Promise<T> implements IPromisE<T>
|
|
|
224
223
|
get rejected(): boolean;
|
|
225
224
|
/** Indicates if the promise has been resolved */
|
|
226
225
|
get resolved(): boolean;
|
|
227
|
-
/**
|
|
226
|
+
/**
|
|
227
|
+
* Get promise status code:
|
|
228
|
+
*
|
|
229
|
+
* - `0` = pending
|
|
230
|
+
* - `1` = resolved
|
|
231
|
+
* - `2` = rejected
|
|
232
|
+
*/
|
|
228
233
|
get state(): 0 | 1 | 2;
|
|
229
234
|
/** Resovle pending promise early. */
|
|
230
235
|
resolve: (value: T | PromiseLike<T>) => void;
|
|
@@ -352,7 +357,7 @@ type TimeoutOptions<Func extends string = 'all'> = {
|
|
|
352
357
|
* @example Explanation & example usage:
|
|
353
358
|
* ```typescript
|
|
354
359
|
* const example = throttle => {
|
|
355
|
-
* const df = PromisE.deferred(throttle)
|
|
360
|
+
* const df = PromisE.deferred({ delayMs: 100, throttle })
|
|
356
361
|
* df(() => PromisE.delay(5000)).then(console.log)
|
|
357
362
|
* df(() => PromisE.delay(500)).then(console.log)
|
|
358
363
|
* df(() => PromisE.delay(1000)).then(console.log)
|
|
@@ -378,8 +383,15 @@ type TimeoutOptions<Func extends string = 'all'> = {
|
|
|
378
383
|
declare function deferred<T, ThisArg = unknown, Delay extends number = number>(options?: DeferredAsyncOptions<ThisArg, Delay>): DeferredAsyncCallback;
|
|
379
384
|
declare namespace deferred {
|
|
380
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
|
+
*/
|
|
381
391
|
delayMs: number;
|
|
392
|
+
/** Set the default error resolution behavior. {@link ResolveError} for all options. */
|
|
382
393
|
resolveError: ResolveError.REJECT;
|
|
394
|
+
/** Set the default ignored resolution behavior. See {@link ResolveIgnored} for all options. */
|
|
383
395
|
resolveIgnored: ResolveIgnored.WITH_LAST;
|
|
384
396
|
};
|
|
385
397
|
}
|
|
@@ -686,7 +698,7 @@ declare class PromisE<T = unknown> extends PromisEBase<T> {
|
|
|
686
698
|
* - `'linear'` uses a constant delay.
|
|
687
699
|
*
|
|
688
700
|
* Default: `'exponential'`
|
|
689
|
-
* @param options.
|
|
701
|
+
* @param options.retryDelay (optional) The base delay in milliseconds between retries.
|
|
690
702
|
*
|
|
691
703
|
* Default: `300`
|
|
692
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
|
}
|
|
@@ -170,105 +176,116 @@ var ResolveIgnored = /* @__PURE__ */ ((ResolveIgnored2) => {
|
|
|
170
176
|
|
|
171
177
|
// src/deferred.ts
|
|
172
178
|
function deferred(options = {}) {
|
|
173
|
-
const { defaults } = deferred;
|
|
174
179
|
options = objCopy(
|
|
175
|
-
defaults,
|
|
180
|
+
deferred.defaults,
|
|
176
181
|
options,
|
|
177
182
|
[],
|
|
178
183
|
"empty"
|
|
179
184
|
);
|
|
180
185
|
let { onError, onIgnore, onResult } = options;
|
|
181
186
|
const {
|
|
182
|
-
delayMs,
|
|
187
|
+
delayMs = 0,
|
|
183
188
|
resolveError,
|
|
184
|
-
// by default reject on error
|
|
185
189
|
resolveIgnored,
|
|
186
190
|
thisArg,
|
|
187
191
|
throttle
|
|
188
192
|
} = options;
|
|
189
|
-
let
|
|
193
|
+
let prevQItem = null;
|
|
190
194
|
const queue = /* @__PURE__ */ new Map();
|
|
191
|
-
const
|
|
195
|
+
const isSequential = !isPositiveNumber(delayMs);
|
|
192
196
|
if (thisArg !== void 0) {
|
|
193
197
|
onError = onError == null ? void 0 : onError.bind(thisArg);
|
|
194
198
|
onIgnore = onIgnore == null ? void 0 : onIgnore.bind(thisArg);
|
|
195
199
|
onResult = onResult == null ? void 0 : onResult.bind(thisArg);
|
|
196
200
|
}
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
201
|
+
const handleRemaining = (currentId) => {
|
|
202
|
+
const _prevQItem = prevQItem;
|
|
203
|
+
prevQItem = null;
|
|
204
|
+
if (isSequential) {
|
|
200
205
|
queue.delete(currentId);
|
|
201
206
|
const [nextId, nextItem] = [...queue.entries()][0] || [];
|
|
202
|
-
return nextId && nextItem &&
|
|
207
|
+
return nextId && nextItem && handleItem(nextId, nextItem);
|
|
208
|
+
}
|
|
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);
|
|
203
217
|
}
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
onIgnore && fallbackIfFails2(onIgnore, [iItem.getPromise], void 0);
|
|
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);
|
|
211
224
|
switch (resolveIgnored) {
|
|
212
225
|
case "WITH_UNDEFINED" /* WITH_UNDEFINED */:
|
|
213
226
|
iItem.resolve(void 0);
|
|
214
227
|
break;
|
|
215
228
|
case "WITH_LAST" /* WITH_LAST */:
|
|
216
|
-
|
|
229
|
+
_prevQItem == null ? void 0 : _prevQItem.then(iItem.resolve, iItem.reject);
|
|
217
230
|
break;
|
|
218
231
|
case "NEVER" /* NEVER */:
|
|
219
232
|
break;
|
|
220
233
|
}
|
|
221
234
|
}
|
|
222
235
|
};
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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
|
+
}
|
|
243
259
|
}
|
|
260
|
+
qItem.completed = true;
|
|
261
|
+
handleRemaining(id);
|
|
244
262
|
};
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
finalizeCb(true, id, qItem),
|
|
251
|
-
finalizeCb(false, id, qItem)
|
|
252
|
-
);
|
|
253
|
-
};
|
|
254
|
-
if (!gotDelay) return execute2;
|
|
255
|
-
const deferFn = throttle ? throttledCore : deferredCore;
|
|
256
|
-
return deferFn(execute2, delayMs, options);
|
|
257
|
-
})();
|
|
263
|
+
const handleItem = isSequential ? executeItem : (throttle ? throttledCore : deferredCore)(
|
|
264
|
+
executeItem,
|
|
265
|
+
delayMs,
|
|
266
|
+
options
|
|
267
|
+
);
|
|
258
268
|
const deferredFunc = (promise) => {
|
|
259
269
|
const id = /* @__PURE__ */ Symbol("deferred-queue-item-id");
|
|
260
270
|
const qItem = new PromisEBase_default();
|
|
261
271
|
qItem.getPromise = isFn2(promise) ? promise : () => promise;
|
|
262
272
|
qItem.started = false;
|
|
263
273
|
queue.set(id, qItem);
|
|
264
|
-
if (
|
|
274
|
+
if (!prevQItem || !isSequential) handleItem(id, qItem);
|
|
265
275
|
return qItem;
|
|
266
276
|
};
|
|
267
277
|
return deferredFunc;
|
|
268
278
|
}
|
|
269
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
|
+
*/
|
|
270
285
|
delayMs: 100,
|
|
286
|
+
/** Set the default error resolution behavior. {@link ResolveError} for all options. */
|
|
271
287
|
resolveError: "REJECT" /* REJECT */,
|
|
288
|
+
/** Set the default ignored resolution behavior. See {@link ResolveIgnored} for all options. */
|
|
272
289
|
resolveIgnored: "WITH_LAST" /* WITH_LAST */
|
|
273
290
|
};
|
|
274
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
|
}
|