@superutils/promise 1.1.6 → 1.2.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 +148 -100
- package/dist/index.js +117 -44
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _superutils_core from '@superutils/core';
|
|
2
|
-
import { ValueOrPromise,
|
|
2
|
+
import { ValueOrPromise, PositiveNumber, DeferredOptions, TimeoutId } from '@superutils/core';
|
|
3
3
|
|
|
4
4
|
interface IPromisE<T = unknown> extends Promise<T> {
|
|
5
5
|
/** 0: pending, 1: resolved, 2: rejected */
|
|
@@ -17,63 +17,6 @@ interface IPromisE<T = unknown> extends Promise<T> {
|
|
|
17
17
|
/** Indicates if the promise has been resolved */
|
|
18
18
|
readonly resolved: boolean;
|
|
19
19
|
}
|
|
20
|
-
interface IPromisE_Delay<T = unknown> extends Promise<T>, IPromisE<T> {
|
|
21
|
-
/**
|
|
22
|
-
* Caution: pausing will prevent the promise from resolving/rejeting automatically.
|
|
23
|
-
*
|
|
24
|
-
* In order to finalize the promise either the `resolve()` or the `reject()` method must be invoked manually.
|
|
25
|
-
*
|
|
26
|
-
* An never-finalized promise may cause memory leak and will leave it at the mercry of the garbage collector.
|
|
27
|
-
* Use `pause()` only if you are sure.
|
|
28
|
-
*
|
|
29
|
-
* @example
|
|
30
|
-
* ```typescript
|
|
31
|
-
* // Example 1: SAFE => no memory leak, because no reference to the promise is stored and no suspended code
|
|
32
|
-
* <button onClick={() => {
|
|
33
|
-
* const promise = PromisE.delay(1000).then(... do stuff ....)
|
|
34
|
-
* setTimeout(() => promise.pause(), 300)
|
|
35
|
-
* }}>Click Me</button>
|
|
36
|
-
* ```
|
|
37
|
-
*
|
|
38
|
-
* @example UNSAFE => potential memory leak, because of suspended code
|
|
39
|
-
* ```typescript
|
|
40
|
-
* <button onClick={() => {
|
|
41
|
-
* const promise = PromisE.delay(1000)
|
|
42
|
-
* setTimeout(() => promise.pause(), 300)
|
|
43
|
-
* await promise // suspended code
|
|
44
|
-
* //... do stuff ....
|
|
45
|
-
* }}>Click Me</button>
|
|
46
|
-
* ```
|
|
47
|
-
*
|
|
48
|
-
* @example UNSAFE => potential memory leak, because of preserved reference.
|
|
49
|
-
* ```typescript
|
|
50
|
-
* // Until the reference to promises is collected by the garbage collector,
|
|
51
|
-
* // reference to the unfinished promise will remain in memory.
|
|
52
|
-
* const promises = []
|
|
53
|
-
* <button onClick={() => {
|
|
54
|
-
* const promise = PromisE.delay(1000)
|
|
55
|
-
* setTimeout(() => promise.pause(), 300)
|
|
56
|
-
* promises.push(promise)
|
|
57
|
-
* }}>Click Me</button>
|
|
58
|
-
* ```
|
|
59
|
-
*/
|
|
60
|
-
pause: () => void;
|
|
61
|
-
/** Timeout ID */
|
|
62
|
-
timeoutId: TimeoutId;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Descibes a timeout PromisE and it's additional properties.
|
|
66
|
-
*/
|
|
67
|
-
type IPromisE_Timeout<T = unknown> = IPromisE<T> & {
|
|
68
|
-
/** Clearing the timeout will prevent it from timing out */
|
|
69
|
-
clearTimeout: () => void;
|
|
70
|
-
/** The result/data promise. If more than one supplied in `args` result promise will be a combined `PromisE.all` */
|
|
71
|
-
data: IPromisE<T>;
|
|
72
|
-
/** A shorthand getter to check if the promise has timed out. Same as `promise.timeout.rejected`. */
|
|
73
|
-
readonly timedout: boolean;
|
|
74
|
-
/** The timeout promise */
|
|
75
|
-
timeout: IPromisE_Delay<T>;
|
|
76
|
-
};
|
|
77
20
|
type OnEarlyFinalize<T> = <TResolved extends boolean, TValue = TResolved extends true ? T : unknown>(resolved: TResolved, resultOrReason: TValue) => ValueOrPromise<unknown>;
|
|
78
21
|
type PromiseParams<T = unknown> = ConstructorParameters<typeof Promise<T>>;
|
|
79
22
|
|
|
@@ -85,7 +28,7 @@ type DeferredAsyncDefaults<ThisArg = unknown, Delay = unknown> = Pick<Required<D
|
|
|
85
28
|
delayMs: number;
|
|
86
29
|
};
|
|
87
30
|
/** Options for `PromisE.deferred` and other related functions */
|
|
88
|
-
type DeferredAsyncOptions<ThisArg = unknown, Delay =
|
|
31
|
+
type DeferredAsyncOptions<ThisArg = unknown, Delay = number> = {
|
|
89
32
|
/**
|
|
90
33
|
* Delay in milliseconds, used for `debounce` and `throttle` modes. Use `0` for sequential execution.
|
|
91
34
|
*
|
|
@@ -93,7 +36,7 @@ type DeferredAsyncOptions<ThisArg = unknown, Delay = unknown> = {
|
|
|
93
36
|
*
|
|
94
37
|
* Default: `100` (or whatever is set in `PromisE.deferred.defaults.delayMs`)
|
|
95
38
|
*/
|
|
96
|
-
delayMs?:
|
|
39
|
+
delayMs?: number | PositiveNumber<Delay>;
|
|
97
40
|
/**
|
|
98
41
|
* Whether to ignore (based on `resolveIgnored` settings) stale promises.
|
|
99
42
|
* In debouce/throttle mode, when an older promise is resolved after a newly resolved promise,
|
|
@@ -126,6 +69,8 @@ type DeferredAsyncOptions<ThisArg = unknown, Delay = unknown> = {
|
|
|
126
69
|
*/
|
|
127
70
|
resolveError?: ResolveError;
|
|
128
71
|
} & (({
|
|
72
|
+
delayMs?: PositiveNumber<Delay>;
|
|
73
|
+
} & DeferredOptions<ThisArg>) | ({
|
|
129
74
|
delayMs: 0;
|
|
130
75
|
} & {
|
|
131
76
|
throttle?: false;
|
|
@@ -133,9 +78,7 @@ type DeferredAsyncOptions<ThisArg = unknown, Delay = unknown> = {
|
|
|
133
78
|
onError?: (this: ThisArg, err: unknown) => ValueOrPromise<unknown>;
|
|
134
79
|
/** The value to be used as "thisArg" whenever any of the callbacks are invoked */
|
|
135
80
|
thisArg?: ThisArg;
|
|
136
|
-
})
|
|
137
|
-
delayMs?: PositiveNumber<Delay>;
|
|
138
|
-
} & DeferredOptions<ThisArg>));
|
|
81
|
+
}));
|
|
139
82
|
/** Determines what to do when deferred promise/function fails */
|
|
140
83
|
declare enum ResolveError {
|
|
141
84
|
/** Neither resolve nor reject the failed */
|
|
@@ -160,6 +103,51 @@ declare enum ResolveIgnored {
|
|
|
160
103
|
WITH_UNDEFINED = "WITH_UNDEFINED"
|
|
161
104
|
}
|
|
162
105
|
|
|
106
|
+
interface IPromisE_Delay<T = unknown> extends Promise<T>, IPromisE<T> {
|
|
107
|
+
/**
|
|
108
|
+
* Caution: pausing will prevent the promise from resolving/rejeting automatically.
|
|
109
|
+
*
|
|
110
|
+
* In order to finalize the promise either the `resolve()` or the `reject()` method must be invoked manually.
|
|
111
|
+
*
|
|
112
|
+
* An never-finalized promise may cause memory leak and will leave it at the mercry of the garbage collector.
|
|
113
|
+
* Use `pause()` only if you are sure.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* // Example 1: SAFE => no memory leak, because no reference to the promise is stored and no suspended code
|
|
118
|
+
* <button onClick={() => {
|
|
119
|
+
* const promise = PromisE.delay(1000).then(... do stuff ....)
|
|
120
|
+
* setTimeout(() => promise.pause(), 300)
|
|
121
|
+
* }}>Click Me</button>
|
|
122
|
+
* ```
|
|
123
|
+
*
|
|
124
|
+
* @example UNSAFE => potential memory leak, because of suspended code
|
|
125
|
+
* ```typescript
|
|
126
|
+
* <button onClick={() => {
|
|
127
|
+
* const promise = PromisE.delay(1000)
|
|
128
|
+
* setTimeout(() => promise.pause(), 300)
|
|
129
|
+
* await promise // suspended code
|
|
130
|
+
* //... do stuff ....
|
|
131
|
+
* }}>Click Me</button>
|
|
132
|
+
* ```
|
|
133
|
+
*
|
|
134
|
+
* @example UNSAFE => potential memory leak, because of preserved reference.
|
|
135
|
+
* ```typescript
|
|
136
|
+
* // Until the reference to promises is collected by the garbage collector,
|
|
137
|
+
* // reference to the unfinished promise will remain in memory.
|
|
138
|
+
* const promises = []
|
|
139
|
+
* <button onClick={() => {
|
|
140
|
+
* const promise = PromisE.delay(1000)
|
|
141
|
+
* setTimeout(() => promise.pause(), 300)
|
|
142
|
+
* promises.push(promise)
|
|
143
|
+
* }}>Click Me</button>
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
pause: () => void;
|
|
147
|
+
/** Timeout ID */
|
|
148
|
+
timeoutId: TimeoutId;
|
|
149
|
+
}
|
|
150
|
+
|
|
163
151
|
/** Function to determine whether retry should be attempted based on previous result/error */
|
|
164
152
|
type RetryIfFunc<T = unknown> = (prevResult: T | undefined, retryCount: number, error?: unknown) => ValueOrPromise<boolean | void>;
|
|
165
153
|
/** Options for automatic retry mechanism */
|
|
@@ -273,7 +261,7 @@ declare class PromisEBase<T = unknown> extends Promise<T> implements IPromisE<T>
|
|
|
273
261
|
/** Sugar for `new PromisE(Promise.race(..))` */
|
|
274
262
|
static race: <T_1 extends unknown[]>(values: T_1) => IPromisE<Awaited<T_1[number]>>;
|
|
275
263
|
/** Extends Promise.reject */
|
|
276
|
-
static reject: <T_1 = never>(reason: unknown) =>
|
|
264
|
+
static reject: <T_1 = never>(reason: unknown) => PromisEBase<T_1>;
|
|
277
265
|
/** Sugar for `new PromisE(Promise.resolve(...))` */
|
|
278
266
|
static resolve: <T_1>(value?: T_1 | PromiseLike<T_1>) => IPromisE<T_1>;
|
|
279
267
|
/** Sugar for `new PromisE(Promise.try(...))` */
|
|
@@ -310,25 +298,62 @@ declare class PromisEBase<T = unknown> extends Promise<T> implements IPromisE<T>
|
|
|
310
298
|
};
|
|
311
299
|
}
|
|
312
300
|
|
|
313
|
-
|
|
301
|
+
/**
|
|
302
|
+
* Descibes a timeout PromisE and it's additional properties.
|
|
303
|
+
*/
|
|
304
|
+
type IPromisE_Timeout<T = unknown> = IPromisE<T> & {
|
|
305
|
+
readonly aborted: boolean;
|
|
306
|
+
/**
|
|
307
|
+
* Removes `abortCtrl/signal` listeners, effectively disabling external cancellation via AbortController.
|
|
308
|
+
*/
|
|
309
|
+
cancelAbort: () => void;
|
|
310
|
+
/**
|
|
311
|
+
* Clears the timeout timer, preventing the promise from being rejected due to a timeout.
|
|
312
|
+
*/
|
|
313
|
+
clearTimeout: () => void;
|
|
314
|
+
/** The underlying data promise. If multiple promises were passed to `timeout`, this represents the combined result (defaulting to `PromisE.all`). */
|
|
315
|
+
data: IPromisE<T>;
|
|
316
|
+
/** Read-only property indicating if the promise timed out. Equivalent to checking `promise.timeout.rejected`. */
|
|
317
|
+
readonly timedout: boolean;
|
|
318
|
+
/** The internal promise that handles the timeout logic. It rejects when the duration expires. */
|
|
319
|
+
timeout: IPromisE_Delay<T>;
|
|
320
|
+
};
|
|
321
|
+
type TimeoutResult<T extends unknown[], TFunc extends keyof TimeoutFunc<T>, Values extends unknown[] = {
|
|
322
|
+
-readonly [P in keyof T]: T[P] extends (...args: unknown[]) => infer ReturnType ? ReturnType : T[P];
|
|
323
|
+
}> = Awaited<T['length'] extends 1 ? Values[0] : ReturnType<TimeoutFunc<Values>[TFunc]>>;
|
|
324
|
+
type TimeoutFunc<T extends unknown[] = []> = {
|
|
314
325
|
all: typeof PromisEBase.all<T>;
|
|
315
326
|
allSettled: typeof PromisEBase.allSettled<T>;
|
|
316
327
|
any: typeof PromisEBase.any<T>;
|
|
317
328
|
race: typeof PromisEBase.race<T>;
|
|
318
329
|
};
|
|
319
330
|
/**
|
|
320
|
-
* `PromisE.timeout`
|
|
331
|
+
* Options for `PromisE.timeout()`
|
|
321
332
|
*
|
|
322
|
-
* @param func (optional) name of the supported `
|
|
333
|
+
* @param func (optional) name of the supported `PromiEBase` static method to be used to resolve
|
|
334
|
+
* when more than one promise/function is provided. Default: `"all"`
|
|
323
335
|
* @param timeout (optional) timeout duration in milliseconds. Default: `10_000` (10 seconds)
|
|
324
336
|
* @param timeoutMsg (optional) timeout error message. Default: `"Timed out after 10000ms"`
|
|
325
337
|
*
|
|
326
338
|
*/
|
|
327
|
-
type TimeoutOptions<Func extends string = 'all'> = {
|
|
328
|
-
|
|
339
|
+
type TimeoutOptions<T extends unknown[] = [], Func extends string = 'all'> = {
|
|
340
|
+
abortCtrl?: AbortController;
|
|
341
|
+
func?: T['length'] extends 0 ? never : T['length'] extends 1 ? never : Func;
|
|
342
|
+
/**
|
|
343
|
+
* Callback invoked when the promise is rejected due to an abort signal.
|
|
344
|
+
* Optionally, return an `Error` object to reject the promise with a custom error.
|
|
345
|
+
*/
|
|
346
|
+
onAbort?: () => ValueOrPromise<void | Error>;
|
|
347
|
+
/**
|
|
348
|
+
* Callback invoked when the promise times out.
|
|
349
|
+
* Optionally, return an `Error` object to reject the promise with a custom error.
|
|
350
|
+
*/
|
|
351
|
+
onTimeout?: () => ValueOrPromise<void | Error>;
|
|
352
|
+
signal?: AbortSignal;
|
|
329
353
|
timeout?: number;
|
|
330
|
-
timeoutMsg?: string;
|
|
331
354
|
};
|
|
355
|
+
/** Default options for `PromisE.timeout()` */
|
|
356
|
+
type TimeoutOptionsDefault = Required<Omit<TimeoutOptions<unknown[], keyof TimeoutFunc>, 'abortCtrl' | 'signal'>>;
|
|
332
357
|
|
|
333
358
|
/**
|
|
334
359
|
* @function PromisE.deferred
|
|
@@ -521,7 +546,7 @@ declare function deferredCallback<TDefault = unknown, ThisArg = unknown, Delay =
|
|
|
521
546
|
* func()
|
|
522
547
|
* ```
|
|
523
548
|
*/
|
|
524
|
-
declare function delay<T = number, TReject extends boolean = boolean>(duration?: number, result?: T | (() => T), asRejected?: TReject): IPromisE_Delay<T>;
|
|
549
|
+
declare function delay<T = number, TReject extends boolean = boolean>(duration?: number, result?: T | (() => T | Promise<T>), asRejected?: TReject): IPromisE_Delay<T>;
|
|
525
550
|
declare namespace delay {
|
|
526
551
|
var defaults: {
|
|
527
552
|
/** Default delay duration in milliseconds */
|
|
@@ -565,18 +590,22 @@ declare namespace delay {
|
|
|
565
590
|
*/
|
|
566
591
|
declare function delayReject<T = never>(duration: number, reason?: unknown): IPromisE_Delay<T>;
|
|
567
592
|
|
|
593
|
+
/** Timeout duration (in milliseconds) used as a fallback when positive number is not provided to {@link timeout} */
|
|
594
|
+
declare const FALLBACK_TIMEOUT = 10000;
|
|
568
595
|
/**
|
|
569
596
|
* Creates a new promise that wraps one or more promises and rejects if they do not settle within a
|
|
570
597
|
* specified timeout duration. When multiple promises are provided, they can be processed using methods like
|
|
571
598
|
* `all` (default), `race`, `any`, or `allSettled`.
|
|
572
599
|
*
|
|
573
600
|
* @param timeout (optional) timeout duration in milliseconds.
|
|
574
|
-
* Default: `
|
|
601
|
+
* Default: `10_000` (10 seconds)
|
|
575
602
|
*
|
|
576
603
|
* @param values rest param containing one or more promises/values
|
|
577
604
|
*
|
|
578
|
-
* @example
|
|
605
|
+
* @example Working with a single promise
|
|
579
606
|
* ```typescript
|
|
607
|
+
* import PromisE from '@supertuils/promise'
|
|
608
|
+
*
|
|
580
609
|
* PromisE.timeout(
|
|
581
610
|
* 5000, // timeout after 5000ms
|
|
582
611
|
* PromisE.delay(1000), // resolves after 1000ms with value 1000
|
|
@@ -584,8 +613,21 @@ declare function delayReject<T = never>(duration: number, reason?: unknown): IPr
|
|
|
584
613
|
* // Result: 1000
|
|
585
614
|
* ```
|
|
586
615
|
*
|
|
616
|
+
* @example Working with a single function
|
|
617
|
+
* ```typescript
|
|
618
|
+
* import PromisE from '@supertuils/promise'
|
|
619
|
+
*
|
|
620
|
+
* PromisE.timeout(
|
|
621
|
+
* 5000, // timeout after 5000ms
|
|
622
|
+
* () => PromisE.delay(1000), // function resolves after 1000ms with value 1000
|
|
623
|
+
* ).then(console.log)
|
|
624
|
+
* // Result: 1000
|
|
625
|
+
* ```
|
|
626
|
+
*
|
|
587
627
|
* @example Promise times out & rejected
|
|
588
628
|
* ```typescript
|
|
629
|
+
* import PromisE from '@supertuils/promise'
|
|
630
|
+
*
|
|
589
631
|
* PromisE.timeout(
|
|
590
632
|
* 5000, // timeout after 5000ms
|
|
591
633
|
* PromisE.delay(20000), // resolves after 20000ms with value 20000
|
|
@@ -593,13 +635,15 @@ declare function delayReject<T = never>(duration: number, reason?: unknown): IPr
|
|
|
593
635
|
* // Error: Error('Timed out after 5000ms')
|
|
594
636
|
*```
|
|
595
637
|
*
|
|
596
|
-
* @example Working with multiple promises, resolved using "PromisE.all()"
|
|
638
|
+
* @example Working with multiple promises/functions, resolved using "PromisE.all()"
|
|
597
639
|
*
|
|
598
640
|
* ```typescript
|
|
641
|
+
* import PromisE from '@supertuils/promise'
|
|
642
|
+
*
|
|
599
643
|
* PromisE.timeout(
|
|
600
644
|
* 5000, // timeout after 5000ms
|
|
601
645
|
* PromisE.delay(1000), // resolves after 1000ms with value 1000
|
|
602
|
-
* PromisE.delay(2000), // resolves after 2000ms with value 2000
|
|
646
|
+
* () => PromisE.delay(2000), // resolves after 2000ms with value 2000
|
|
603
647
|
* PromisE.delay(3000), // resolves after 3000ms with value 3000
|
|
604
648
|
* ).then(console.log)
|
|
605
649
|
* // Result: [ 1000, 2000, 3000 ]
|
|
@@ -608,6 +652,8 @@ declare function delayReject<T = never>(duration: number, reason?: unknown): IPr
|
|
|
608
652
|
* @example Promise times out & but not rejected.
|
|
609
653
|
* Eg: when API request is taking longer than expected, print a message avoid rejecting the promise.
|
|
610
654
|
* ```typescript
|
|
655
|
+
* import PromisE from '@supertuils/promise'
|
|
656
|
+
*
|
|
611
657
|
* const promise = PromisE.timeout(
|
|
612
658
|
* 5000, // timeout after 5000ms
|
|
613
659
|
* PromisE.delay(20000), // data promise, resolves after 20000ms with value 20000
|
|
@@ -622,10 +668,32 @@ declare function delayReject<T = never>(duration: number, reason?: unknown): IPr
|
|
|
622
668
|
* return promise.data
|
|
623
669
|
* })
|
|
624
670
|
*```
|
|
671
|
+
*/
|
|
672
|
+
declare function timeout<T extends [unknown, ...unknown[]]>(timeout: number, ...values: T): IPromisE_Timeout<TimeoutResult<T, 'all'>>;
|
|
673
|
+
/**
|
|
674
|
+
*
|
|
675
|
+
* @param options An options object can be passed with one or more of the following properties:
|
|
676
|
+
* @param options.abortCtrl (optional) AbortController to manually reject promise externally and/or to sync abort with timeout rejection
|
|
677
|
+
* @param options.abortMsg (optional) error message when promise is rejected by abort controller/signal
|
|
678
|
+
* @param options.func (optional) Name of the `PromisE` static method to be used to combine the `values`.
|
|
679
|
+
* Only used when more than one promise is provided. Default: `"all"`
|
|
680
|
+
*
|
|
681
|
+
* Accepted values:
|
|
682
|
+
* 1. `'all'` **(default)**: for `PromisE.all`
|
|
683
|
+
* 2. `'allSettled'`: for `PromisE.allSettled`
|
|
684
|
+
* 3. `'any'`: for `PromisE.any`
|
|
685
|
+
* 4. `'race'`: for `PromisE.race`
|
|
686
|
+
* @param options.signal (optional) AbortSignal to manually reject promise externally
|
|
687
|
+
* @param options.timeout (optional) timeout duration in milliseconds. If positive number is not provided, the default value will be used. Default: `10_000` (10 seconds)
|
|
688
|
+
* @param options.timeoutMsg (optional) custom error message to be used when promises timeout.
|
|
689
|
+
*
|
|
690
|
+
* @param values Mix of promises, values and/or functions
|
|
625
691
|
*
|
|
626
|
-
* @example
|
|
692
|
+
* @example Working with multiple promises/functions resolved using "PromisE.race()"
|
|
627
693
|
*
|
|
628
694
|
* ```typescript
|
|
695
|
+
* import PromisE from '@supertuils/promise'
|
|
696
|
+
*
|
|
629
697
|
* PromisE.timeout(
|
|
630
698
|
* { // instead of `timeout: number` an object can be used for additional options
|
|
631
699
|
* func: 'race', // tells PromisE.timeout to use `PromisE.race(promises)`
|
|
@@ -633,35 +701,15 @@ declare function delayReject<T = never>(duration: number, reason?: unknown): IPr
|
|
|
633
701
|
* timeoutMsg: 'My custom timed out message',
|
|
634
702
|
* },
|
|
635
703
|
* PromisE.delay(1000), // resolves after 1000ms with value 1000
|
|
636
|
-
* PromisE.delay(2000), // resolves after 2000ms with value 2000
|
|
704
|
+
* () => PromisE.delay(2000), // resolves after 2000ms with value 2000
|
|
637
705
|
* PromisE.delay(3000), // resolves after 3000ms with value 3000
|
|
638
706
|
* ).then(console.log)
|
|
639
707
|
* // Result: 1000 (Result of `Promise.race(promises)`)
|
|
640
708
|
* ```
|
|
641
709
|
*/
|
|
642
|
-
declare function timeout<T extends
|
|
643
|
-
Result = T['length'] extends 1 ? Awaited<T[0]> : Awaited<T[number]>[]>(timeout: number, ...values: T): IPromisE_Timeout<Result>;
|
|
644
|
-
/**
|
|
645
|
-
*
|
|
646
|
-
* @param options An options object can be passed with one or more of the following properties:
|
|
647
|
-
* @param options.func (optional) Name of the `PromisE` method to be used to combine the `values`.
|
|
648
|
-
* Only used when more than one promise is provided.
|
|
649
|
-
*
|
|
650
|
-
* Accepted values:
|
|
651
|
-
* 1. `'all'` **(default)**: for `PromisE.all`
|
|
652
|
-
* 2. `'allSettled'`: for `PromisE.allSettled`
|
|
653
|
-
* 3. `'any'`: for `PromisE.any`
|
|
654
|
-
* 4. `'race'`: for `PromisE.race`
|
|
655
|
-
*
|
|
656
|
-
* @param options.timeout (optional) timeout duration in milliseconds. Default: `10_000` (10 seconds)
|
|
657
|
-
* @param options.timeoutMsg (optional) custom error message to be used when promises timeout.
|
|
658
|
-
*
|
|
659
|
-
* @param values
|
|
660
|
-
*/
|
|
661
|
-
declare function timeout<T extends [unknown, ...unknown[]], // require at least one value
|
|
662
|
-
TFunc extends keyof TimeoutFunc<T>, Result = T['length'] extends 1 ? Awaited<T[0]> : Awaited<ReturnType<TimeoutFunc<T>[TFunc]>>>(options: TimeoutOptions<TFunc>, ...values: T): IPromisE_Timeout<Result>;
|
|
710
|
+
declare function timeout<T extends unknown[], TFunc extends keyof TimeoutFunc<T> = keyof TimeoutFunc<T>>(options: TimeoutOptions<T, TFunc>, ...values: T): IPromisE_Timeout<TimeoutResult<T, TFunc>>;
|
|
663
711
|
declare namespace timeout {
|
|
664
|
-
var
|
|
712
|
+
var defaults: Required<Omit<TimeoutOptions<unknown[], keyof TimeoutFunc<[]>>, "abortCtrl" | "signal">>;
|
|
665
713
|
}
|
|
666
714
|
|
|
667
715
|
/**
|
|
@@ -792,4 +840,4 @@ declare const retry: {
|
|
|
792
840
|
};
|
|
793
841
|
};
|
|
794
842
|
|
|
795
|
-
export { type DeferredAsyncCallback, type DeferredAsyncDefaults, type DeferredAsyncOptions, type GetPromiseFunc, type IPromisE, type IPromisE_Delay, type IPromisE_Timeout, type OnEarlyFinalize, PromisE, PromisEBase, type PromiseParams, ResolveError, ResolveIgnored, type RetryIfFunc, type RetryOptions, type TimeoutFunc, type TimeoutOptions, PromisE as default, deferred, deferredCallback, delay, delayReject, retry, timeout };
|
|
843
|
+
export { type DeferredAsyncCallback, type DeferredAsyncDefaults, type DeferredAsyncOptions, FALLBACK_TIMEOUT, type GetPromiseFunc, type IPromisE, type IPromisE_Delay, type IPromisE_Timeout, type OnEarlyFinalize, PromisE, PromisEBase, type PromiseParams, ResolveError, ResolveIgnored, type RetryIfFunc, type RetryOptions, type TimeoutFunc, type TimeoutOptions, type TimeoutOptionsDefault, type TimeoutResult, PromisE as default, deferred, deferredCallback, delay, delayReject, retry, timeout };
|
package/dist/index.js
CHANGED
|
@@ -87,11 +87,6 @@ var _PromisEBase = class _PromisEBase extends Promise {
|
|
|
87
87
|
get state() {
|
|
88
88
|
return this._state;
|
|
89
89
|
}
|
|
90
|
-
// static withResolvers = <T = unknown>() => {
|
|
91
|
-
// const pwr = globalThis.Promise.withResolvers<T>()
|
|
92
|
-
// const promise = new PromisEBase<T>(pwr.promise) as IPromisE<T>
|
|
93
|
-
// return { ...pwr, promise }
|
|
94
|
-
// }
|
|
95
90
|
};
|
|
96
91
|
//
|
|
97
92
|
//
|
|
@@ -108,8 +103,8 @@ _PromisEBase.any = (values) => new _PromisEBase(globalThis.Promise.any(values));
|
|
|
108
103
|
_PromisEBase.race = (values) => new _PromisEBase(globalThis.Promise.race(values));
|
|
109
104
|
/** Extends Promise.reject */
|
|
110
105
|
_PromisEBase.reject = (reason) => {
|
|
111
|
-
const
|
|
112
|
-
queueMicrotask(() => reject(reason));
|
|
106
|
+
const promise = new _PromisEBase();
|
|
107
|
+
queueMicrotask(() => promise.reject(reason));
|
|
113
108
|
return promise;
|
|
114
109
|
};
|
|
115
110
|
/** Sugar for `new PromisE(Promise.resolve(...))` */
|
|
@@ -312,23 +307,28 @@ var deferredCallback_default = deferredCallback;
|
|
|
312
307
|
|
|
313
308
|
// src/delay.ts
|
|
314
309
|
import { fallbackIfFails as fallbackIfFails3, isFn as isFn3 } from "@superutils/core";
|
|
315
|
-
function delay(duration = delay.defaults.duration, result
|
|
310
|
+
function delay(duration = delay.defaults.duration, result, asRejected = false) {
|
|
316
311
|
const promise = new PromisEBase_default();
|
|
317
312
|
const finalize = (result2) => {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
313
|
+
const _result = fallbackIfFails3(
|
|
314
|
+
async () => {
|
|
315
|
+
const _result2 = await (isFn3(result2) ? result2() : result2);
|
|
316
|
+
return !asRejected ? _result2 != null ? _result2 : duration : _result2 != null ? _result2 : new Error(
|
|
317
|
+
`${delay.defaults.delayTimeoutMsg} ${duration}ms`
|
|
318
|
+
);
|
|
319
|
+
},
|
|
320
|
+
[],
|
|
321
|
+
// when result is a function and it fails/rejects,
|
|
322
|
+
// promise will reject even if `asRejected = false`
|
|
323
|
+
(err) => Promise.reject(err)
|
|
326
324
|
);
|
|
325
|
+
!asRejected ? promise.resolve(_result) : _result.then(promise.reject, promise.reject);
|
|
327
326
|
};
|
|
328
327
|
promise.timeoutId = setTimeout(() => finalize(result), duration);
|
|
329
328
|
promise.pause = () => clearTimeout(promise.timeoutId);
|
|
330
329
|
promise.catch(() => {
|
|
331
330
|
}).finally(() => promise.pause());
|
|
331
|
+
promise.onEarlyFinalize.push(() => promise.pause());
|
|
332
332
|
return promise;
|
|
333
333
|
}
|
|
334
334
|
delay.defaults = {
|
|
@@ -412,44 +412,116 @@ retry.defaults = {
|
|
|
412
412
|
var retry_default = retry;
|
|
413
413
|
|
|
414
414
|
// src/timeout.ts
|
|
415
|
-
import {
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
const
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
415
|
+
import {
|
|
416
|
+
arrUnique,
|
|
417
|
+
fallbackIfFails as fallbackIfFails5,
|
|
418
|
+
isFn as isFn4,
|
|
419
|
+
isObj,
|
|
420
|
+
isPositiveNumber as isPositiveNumber2,
|
|
421
|
+
noop,
|
|
422
|
+
objCopy as objCopy3
|
|
423
|
+
} from "@superutils/core";
|
|
424
|
+
var FALLBACK_TIMEOUT = 1e4;
|
|
425
|
+
function timeout(timeoutOrOptions, ...values) {
|
|
426
|
+
const options = objCopy3(
|
|
427
|
+
timeout.defaults,
|
|
428
|
+
isObj(timeoutOrOptions) ? timeoutOrOptions : { timeout: timeoutOrOptions },
|
|
429
|
+
[],
|
|
430
|
+
"empty"
|
|
431
|
+
);
|
|
432
|
+
const { func, onTimeout } = options;
|
|
433
|
+
const duration = isPositiveNumber2(options.timeout) ? options.timeout : FALLBACK_TIMEOUT;
|
|
434
|
+
const arrPromises = values.map((v) => isFn4(v) ? PromisEBase_default.try(v) : v);
|
|
435
|
+
const dataPromise = arrPromises.length <= 1 ? (
|
|
436
|
+
// single promise resolves to a single result
|
|
437
|
+
arrPromises[0] instanceof PromisEBase_default ? arrPromises[0] : new PromisEBase_default(arrPromises[0])
|
|
438
|
+
) : (
|
|
439
|
+
// multiple promises resolve to an array of results
|
|
440
|
+
(isFn4(PromisEBase_default[func]) ? PromisEBase_default[func] : PromisEBase_default.all)(
|
|
441
|
+
arrPromises
|
|
442
|
+
)
|
|
431
443
|
);
|
|
444
|
+
const timeoutPromise = delayReject_default(duration, onTimeout);
|
|
432
445
|
const promise = PromisEBase_default.race([
|
|
433
446
|
dataPromise,
|
|
434
447
|
timeoutPromise
|
|
435
448
|
]);
|
|
436
|
-
promise
|
|
437
|
-
promise.data = dataPromise;
|
|
438
|
-
promise.timeout = timeoutPromise;
|
|
439
|
-
Object.defineProperty(promise, "timedout", {
|
|
440
|
-
get: () => promise.timeout.rejected
|
|
441
|
-
});
|
|
442
|
-
dataPromise.catch(() => {
|
|
443
|
-
}).finally(() => {
|
|
444
|
-
promise.clearTimeout();
|
|
445
|
-
});
|
|
449
|
+
addPropsNListeners(promise, dataPromise, timeoutPromise, options);
|
|
446
450
|
return promise;
|
|
447
451
|
}
|
|
448
|
-
timeout.
|
|
452
|
+
timeout.defaults = {
|
|
449
453
|
func: "all",
|
|
450
|
-
timeout:
|
|
454
|
+
timeout: FALLBACK_TIMEOUT
|
|
451
455
|
};
|
|
452
456
|
var timeout_default = timeout;
|
|
457
|
+
var addPropsNListeners = (promise, dataPromise, timeoutPromise, options) => {
|
|
458
|
+
const { abortCtrl, onAbort, signal } = options;
|
|
459
|
+
const signals = arrUnique([abortCtrl == null ? void 0 : abortCtrl.signal, signal].filter(Boolean));
|
|
460
|
+
Object.defineProperties(promise, {
|
|
461
|
+
aborted: {
|
|
462
|
+
get() {
|
|
463
|
+
return promise.rejected && !!signals.find((s) => s.aborted);
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
cancelAbort: {
|
|
467
|
+
get() {
|
|
468
|
+
return () => {
|
|
469
|
+
signals == null ? void 0 : signals.forEach(
|
|
470
|
+
(signal2) => signal2.removeEventListener("abort", handleAbort)
|
|
471
|
+
);
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
},
|
|
475
|
+
clearTimeout: {
|
|
476
|
+
get() {
|
|
477
|
+
return () => clearTimeout(timeoutPromise.timeoutId);
|
|
478
|
+
}
|
|
479
|
+
},
|
|
480
|
+
data: {
|
|
481
|
+
get() {
|
|
482
|
+
return dataPromise;
|
|
483
|
+
}
|
|
484
|
+
},
|
|
485
|
+
timeout: {
|
|
486
|
+
get() {
|
|
487
|
+
return timeoutPromise;
|
|
488
|
+
}
|
|
489
|
+
},
|
|
490
|
+
timedout: {
|
|
491
|
+
get() {
|
|
492
|
+
return promise.rejected && timeoutPromise.rejected;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
const cleanup = () => {
|
|
497
|
+
promise.cancelAbort();
|
|
498
|
+
promise.clearTimeout();
|
|
499
|
+
};
|
|
500
|
+
promise.onEarlyFinalize.push(cleanup);
|
|
501
|
+
promise.catch(() => {
|
|
502
|
+
var _a;
|
|
503
|
+
if (!timeoutPromise.rejected && !signals.find((x) => x.aborted))
|
|
504
|
+
return;
|
|
505
|
+
((_a = abortCtrl == null ? void 0 : abortCtrl.signal) == null ? void 0 : _a.aborted) === false && abortCtrl.abort();
|
|
506
|
+
}).finally(cleanup);
|
|
507
|
+
if (!signals.length) return;
|
|
508
|
+
const started = /* @__PURE__ */ new Date();
|
|
509
|
+
function handleAbort() {
|
|
510
|
+
if (!promise.pending) return;
|
|
511
|
+
fallbackIfFails5(async () => await (onAbort == null ? void 0 : onAbort()), [], void 0).then(
|
|
512
|
+
(err) => {
|
|
513
|
+
var _a;
|
|
514
|
+
err != null ? err : err = new Error(
|
|
515
|
+
`Aborted after ${(/* @__PURE__ */ new Date()).getTime() - started.getTime()}ms`
|
|
516
|
+
);
|
|
517
|
+
(_a = err.name) != null ? _a : err.name = "AbortError";
|
|
518
|
+
promise.reject(err);
|
|
519
|
+
},
|
|
520
|
+
noop
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
signals.forEach((signal2) => signal2.addEventListener("abort", handleAbort));
|
|
524
|
+
};
|
|
453
525
|
|
|
454
526
|
// src/PromisE.ts
|
|
455
527
|
var PromisE = class extends PromisEBase_default {
|
|
@@ -465,6 +537,7 @@ var PromisE_default = PromisE;
|
|
|
465
537
|
// src/index.ts
|
|
466
538
|
var index_default = PromisE_default;
|
|
467
539
|
export {
|
|
540
|
+
FALLBACK_TIMEOUT,
|
|
468
541
|
PromisE,
|
|
469
542
|
PromisEBase,
|
|
470
543
|
ResolveError,
|
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.1.
|
|
7
|
+
"@superutils/core": "^1.1.8"
|
|
8
8
|
},
|
|
9
9
|
"description": "An extended Promise with additional 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.2.0"
|
|
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.
|
|
46
|
+
"version": "1.2.0"
|
|
47
47
|
}
|