@byloth/core 2.0.0-rc.1 → 2.0.0-rc.11
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/core.js +1395 -894
- package/dist/core.js.map +1 -1
- package/dist/core.umd.cjs +3 -3
- package/dist/core.umd.cjs.map +1 -1
- package/package.json +8 -10
- package/src/helpers.ts +7 -0
- package/src/index.ts +19 -14
- package/src/models/aggregators/aggregated-async-iterator.ts +129 -81
- package/src/models/aggregators/aggregated-iterator.ts +128 -82
- package/src/models/aggregators/index.ts +1 -3
- package/src/models/aggregators/reduced-iterator.ts +118 -30
- package/src/models/aggregators/types.ts +15 -10
- package/src/models/callbacks/callable-object.ts +25 -0
- package/src/models/callbacks/index.ts +5 -0
- package/src/models/callbacks/publisher.ts +64 -0
- package/src/models/callbacks/switchable-callback.ts +110 -0
- package/src/models/callbacks/types.ts +1 -0
- package/src/models/exceptions/core.ts +3 -3
- package/src/models/exceptions/index.ts +13 -13
- package/src/models/game-loop.ts +9 -9
- package/src/models/index.ts +3 -6
- package/src/models/iterators/smart-async-iterator.ts +109 -23
- package/src/models/iterators/smart-iterator.ts +105 -12
- package/src/models/iterators/types.ts +17 -7
- package/src/models/json/json-storage.ts +2 -3
- package/src/models/json/types.ts +3 -1
- package/src/models/promises/deferred-promise.ts +1 -1
- package/src/models/promises/index.ts +3 -1
- package/src/models/promises/long-running-task.ts +294 -0
- package/src/models/promises/smart-promise.ts +6 -1
- package/src/models/promises/thenable.ts +97 -0
- package/src/models/promises/timed-promise.ts +1 -1
- package/src/models/promises/types.ts +2 -0
- package/src/models/timers/clock.ts +29 -7
- package/src/models/timers/countdown.ts +56 -20
- package/src/models/types.ts +12 -10
- package/src/utils/async.ts +9 -4
- package/src/utils/date.ts +3 -0
- package/src/utils/index.ts +1 -1
- package/src/utils/random.ts +4 -3
- package/src/models/aggregators/aggregator.ts +0 -46
- package/src/models/aggregators/async-aggregator.ts +0 -56
- package/src/models/publisher.ts +0 -39
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import AggregatedIterator from "../aggregators/aggregated-iterator.js";
|
|
1
2
|
import { ValueException } from "../exceptions/index.js";
|
|
2
3
|
|
|
3
|
-
import type { GeneratorFunction, Iteratee, TypeGuardIteratee, Reducer,
|
|
4
|
+
import type { GeneratorFunction, Iteratee, TypeGuardIteratee, Reducer, IteratorLike } from "./types.js";
|
|
4
5
|
|
|
5
6
|
export default class SmartIterator<T, R = void, N = undefined> implements Iterator<T, R, N>
|
|
6
7
|
{
|
|
@@ -9,11 +10,11 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
|
|
|
9
10
|
public return?: (value?: R) => IteratorResult<T, R>;
|
|
10
11
|
public throw?: (error?: unknown) => IteratorResult<T, R>;
|
|
11
12
|
|
|
12
|
-
public constructor(iterable: Iterable<T>);
|
|
13
|
+
public constructor(iterable: Iterable<T, R, N>);
|
|
13
14
|
public constructor(iterator: Iterator<T, R, N>);
|
|
14
15
|
public constructor(generatorFn: GeneratorFunction<T, R, N>);
|
|
15
|
-
public constructor(argument:
|
|
16
|
-
public constructor(argument:
|
|
16
|
+
public constructor(argument: IteratorLike<T, R, N> | GeneratorFunction<T, R, N>);
|
|
17
|
+
public constructor(argument: IteratorLike<T, R, N> | GeneratorFunction<T, R, N>)
|
|
17
18
|
{
|
|
18
19
|
if (argument instanceof Function)
|
|
19
20
|
{
|
|
@@ -28,15 +29,14 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
|
|
|
28
29
|
this._iterator = argument;
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
if (this._iterator.return) { this.return = (value
|
|
32
|
-
if (this._iterator.throw) { this.throw = (error
|
|
32
|
+
if (this._iterator.return) { this.return = (value) => this._iterator.return!(value); }
|
|
33
|
+
if (this._iterator.throw) { this.throw = (error) => this._iterator.throw!(error); }
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
public every(predicate: Iteratee<T, boolean>): boolean
|
|
36
37
|
{
|
|
37
38
|
let index = 0;
|
|
38
39
|
|
|
39
|
-
// eslint-disable-next-line no-constant-condition
|
|
40
40
|
while (true)
|
|
41
41
|
{
|
|
42
42
|
const result = this._iterator.next();
|
|
@@ -51,7 +51,6 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
|
|
|
51
51
|
{
|
|
52
52
|
let index = 0;
|
|
53
53
|
|
|
54
|
-
// eslint-disable-next-line no-constant-condition
|
|
55
54
|
while (true)
|
|
56
55
|
{
|
|
57
56
|
const result = this._iterator.next();
|
|
@@ -118,7 +117,6 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
|
|
|
118
117
|
index += 1;
|
|
119
118
|
}
|
|
120
119
|
|
|
121
|
-
// eslint-disable-next-line no-constant-condition
|
|
122
120
|
while (true)
|
|
123
121
|
{
|
|
124
122
|
const result = this._iterator.next();
|
|
@@ -130,6 +128,92 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
|
|
|
130
128
|
}
|
|
131
129
|
}
|
|
132
130
|
|
|
131
|
+
public flatMap<V>(iteratee: Iteratee<T, Iterable<V>>): SmartIterator<V, R>
|
|
132
|
+
{
|
|
133
|
+
const iterator = this._iterator;
|
|
134
|
+
|
|
135
|
+
return new SmartIterator<V, R>(function* ()
|
|
136
|
+
{
|
|
137
|
+
let index = 0;
|
|
138
|
+
|
|
139
|
+
while (true)
|
|
140
|
+
{
|
|
141
|
+
const result = iterator.next();
|
|
142
|
+
if (result.done) { return result.value; }
|
|
143
|
+
|
|
144
|
+
const iterable = iteratee(result.value, index);
|
|
145
|
+
for (const value of iterable)
|
|
146
|
+
{
|
|
147
|
+
yield value;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
index += 1;
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public drop(count: number): SmartIterator<T, R | undefined>
|
|
156
|
+
{
|
|
157
|
+
const iterator = this._iterator;
|
|
158
|
+
|
|
159
|
+
return new SmartIterator<T, R | undefined>(function* ()
|
|
160
|
+
{
|
|
161
|
+
let index = 0;
|
|
162
|
+
while (index < count)
|
|
163
|
+
{
|
|
164
|
+
const result = iterator.next();
|
|
165
|
+
if (result.done) { return; }
|
|
166
|
+
|
|
167
|
+
index += 1;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
while (true)
|
|
171
|
+
{
|
|
172
|
+
const result = iterator.next();
|
|
173
|
+
if (result.done) { return result.value; }
|
|
174
|
+
|
|
175
|
+
yield result.value;
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
public take(limit: number): SmartIterator<T, R | undefined>
|
|
180
|
+
{
|
|
181
|
+
const iterator = this._iterator;
|
|
182
|
+
|
|
183
|
+
return new SmartIterator<T, R | undefined>(function* ()
|
|
184
|
+
{
|
|
185
|
+
let index = 0;
|
|
186
|
+
while (index < limit)
|
|
187
|
+
{
|
|
188
|
+
const result = iterator.next();
|
|
189
|
+
if (result.done) { return result.value; }
|
|
190
|
+
|
|
191
|
+
yield result.value;
|
|
192
|
+
|
|
193
|
+
index += 1;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return;
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
public find(predicate: Iteratee<T, boolean>): T | undefined;
|
|
201
|
+
public find<S extends T>(predicate: TypeGuardIteratee<T, S>): S | undefined;
|
|
202
|
+
public find(predicate: Iteratee<T, boolean>): T | undefined
|
|
203
|
+
{
|
|
204
|
+
let index = 0;
|
|
205
|
+
|
|
206
|
+
while (true)
|
|
207
|
+
{
|
|
208
|
+
const result = this._iterator.next();
|
|
209
|
+
|
|
210
|
+
if (result.done) { return; }
|
|
211
|
+
if (predicate(result.value, index)) { return result.value; }
|
|
212
|
+
|
|
213
|
+
index += 1;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
133
217
|
public enumerate(): SmartIterator<[number, T], R>
|
|
134
218
|
{
|
|
135
219
|
return this.map((value, index) => [index, value]);
|
|
@@ -160,7 +244,6 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
|
|
|
160
244
|
{
|
|
161
245
|
let index = 0;
|
|
162
246
|
|
|
163
|
-
// eslint-disable-next-line no-constant-condition
|
|
164
247
|
while (true)
|
|
165
248
|
{
|
|
166
249
|
const result = this._iterator.next();
|
|
@@ -169,11 +252,11 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
|
|
|
169
252
|
index += 1;
|
|
170
253
|
}
|
|
171
254
|
}
|
|
255
|
+
|
|
172
256
|
public forEach(iteratee: Iteratee<T>): void
|
|
173
257
|
{
|
|
174
258
|
let index = 0;
|
|
175
259
|
|
|
176
|
-
// eslint-disable-next-line no-constant-condition
|
|
177
260
|
while (true)
|
|
178
261
|
{
|
|
179
262
|
const result = this._iterator.next();
|
|
@@ -190,12 +273,22 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
|
|
|
190
273
|
return this._iterator.next(...values);
|
|
191
274
|
}
|
|
192
275
|
|
|
276
|
+
public groupBy<K extends PropertyKey>(iteratee: Iteratee<T, K>): AggregatedIterator<K, T>
|
|
277
|
+
{
|
|
278
|
+
return new AggregatedIterator(this.map((element, index) =>
|
|
279
|
+
{
|
|
280
|
+
const key = iteratee(element, index);
|
|
281
|
+
|
|
282
|
+
return [key, element] as [K, T];
|
|
283
|
+
}));
|
|
284
|
+
}
|
|
285
|
+
|
|
193
286
|
public toArray(): T[]
|
|
194
287
|
{
|
|
195
288
|
return Array.from(this as Iterable<T>);
|
|
196
289
|
}
|
|
197
290
|
|
|
198
|
-
public
|
|
291
|
+
public readonly [Symbol.toStringTag]: string = "SmartIterator";
|
|
199
292
|
|
|
200
293
|
public [Symbol.iterator](): SmartIterator<T, R, N> { return this; }
|
|
201
294
|
}
|
|
@@ -1,20 +1,30 @@
|
|
|
1
|
+
|
|
1
2
|
import type { MaybePromise } from "../promises/types.js";
|
|
2
3
|
|
|
4
|
+
export type MaybeAsyncIterable<T, R = void, N = undefined> = Iterable<T, R, N> | AsyncIterable<T, R, N>;
|
|
5
|
+
export type MaybeAsyncIterator<T, R = void, N = undefined> = Iterator<T, R, N> | AsyncIterator<T, R, N>;
|
|
6
|
+
export type MaybeAsyncGenerator<T, R = void, N = undefined> = Generator<T, R, N> | AsyncGenerator<T, R, N>;
|
|
7
|
+
|
|
3
8
|
export type GeneratorFunction<T, R = void, N = undefined> = () => Generator<T, R, N>;
|
|
4
9
|
export type AsyncGeneratorFunction<T, R = void, N = undefined> = () => AsyncGenerator<T, R, N>;
|
|
10
|
+
export type MaybeAsyncGeneratorFunction<T, R = void, N = undefined> = () => MaybeAsyncGenerator<T, R, N>;
|
|
5
11
|
|
|
6
12
|
export type Iteratee<T, R = void> = (value: T, index: number) => R;
|
|
13
|
+
export type AsyncIteratee<T, R = void> = (value: T, index: number) => Promise<R>;
|
|
7
14
|
export type MaybeAsyncIteratee<T, R = void> = (value: T, index: number) => MaybePromise<R>;
|
|
8
15
|
|
|
9
16
|
export type TypeGuardIteratee<T, R extends T> = (value: T, index: number) => value is R;
|
|
10
|
-
|
|
11
|
-
|
|
17
|
+
|
|
18
|
+
// @ts-expect-error - This is an asyncronous type guard iteratee that guarantees the return value is a promise.
|
|
19
|
+
export type AsyncTypeGuardIteratee<T, R extends T> = (value: T, index: number) => value is Promise<R>;
|
|
20
|
+
|
|
21
|
+
// @ts-expect-error - This may be an asyncronous type guard iteratee that guarantees the return value may be a promise.
|
|
22
|
+
export type MaybeAsyncTypeGuardIteratee<T, R extends T> = (value: T, index: number) => value is MaybePromise<R>;
|
|
12
23
|
|
|
13
24
|
export type Reducer<T, A> = (accumulator: A, value: T, index: number) => A;
|
|
25
|
+
export type AsyncReducer<T, A> = (accumulator: A, value: T, index: number) => Promise<A>;
|
|
14
26
|
export type MaybeAsyncReducer<T, A> = (accumulator: A, value: T, index: number) => MaybePromise<A>;
|
|
15
27
|
|
|
16
|
-
export type
|
|
17
|
-
export type
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
export type MaybeAsyncIterLike<T, R = void, N = undefined> = IterLike<T, R, N> | AsyncIterLike<T, R, N>;
|
|
28
|
+
export type IteratorLike<T, R = void, N = undefined> = Iterable<T> | Iterator<T, R, N>;
|
|
29
|
+
export type AsyncIteratorLike<T, R = void, N = undefined> = AsyncIterable<T> | AsyncIterator<T, R, N>;
|
|
30
|
+
export type MaybeAsyncIteratorLike<T, R = void, N = undefined> = IteratorLike<T, R, N> | AsyncIteratorLike<T, R, N>;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable no-trailing-spaces */
|
|
2
1
|
|
|
3
2
|
import { isBrowser } from "../../helpers.js";
|
|
4
3
|
import { EnvironmentException } from "../exceptions/index.js";
|
|
@@ -45,7 +44,7 @@ export default class JSONStorage
|
|
|
45
44
|
{
|
|
46
45
|
return JSON.parse(propertyValue);
|
|
47
46
|
}
|
|
48
|
-
catch
|
|
47
|
+
catch
|
|
49
48
|
{
|
|
50
49
|
// eslint-disable-next-line no-console
|
|
51
50
|
console.warn(
|
|
@@ -252,5 +251,5 @@ export default class JSONStorage
|
|
|
252
251
|
this._persistent.removeItem(propertyName);
|
|
253
252
|
}
|
|
254
253
|
|
|
255
|
-
public
|
|
254
|
+
public readonly [Symbol.toStringTag]: string = "JSONStorage";
|
|
256
255
|
}
|
package/src/models/json/types.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export type JSONArray = JSONValue[];
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style
|
|
4
|
+
export interface JSONObject { [key: string]: JSONValue }
|
|
3
5
|
export type JSONValue = boolean | number | string | null | JSONObject | JSONArray;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import DeferredPromise from "./deferred-promise.js";
|
|
2
|
+
import LongRunningTask from "./long-running-task.js";
|
|
2
3
|
import SmartPromise from "./smart-promise.js";
|
|
4
|
+
import Thenable from "./thenable.js";
|
|
3
5
|
import TimedPromise from "./timed-promise.js";
|
|
4
6
|
|
|
5
|
-
export { DeferredPromise, SmartPromise, TimedPromise };
|
|
7
|
+
export { DeferredPromise, LongRunningTask, SmartPromise, Thenable, TimedPromise };
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { yieldToEventLoop } from "../../utils/async.js";
|
|
2
|
+
|
|
3
|
+
import Publisher from "../callbacks/publisher.js";
|
|
4
|
+
import { RuntimeException } from "../exceptions/index.js";
|
|
5
|
+
|
|
6
|
+
import type { MaybeAsyncGeneratorFunction } from "../iterators/types.js";
|
|
7
|
+
import type { FulfilledHandler, PromiseExecutor, RejectedHandler } from "./types.js";
|
|
8
|
+
|
|
9
|
+
export interface LongRunningTaskOptions
|
|
10
|
+
{
|
|
11
|
+
ignoreErrors?: boolean;
|
|
12
|
+
stepIncrement?: number;
|
|
13
|
+
totalSteps?: number | null;
|
|
14
|
+
trackProgress?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default class LongRunningTask<T = void> implements Promise<T>
|
|
18
|
+
{
|
|
19
|
+
private static get _DefaultOptions(): Required<LongRunningTaskOptions>
|
|
20
|
+
{
|
|
21
|
+
return {
|
|
22
|
+
ignoreErrors: false,
|
|
23
|
+
stepIncrement: 1,
|
|
24
|
+
totalSteps: null,
|
|
25
|
+
trackProgress: false
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
protected _startTime: number;
|
|
30
|
+
protected _estimatedTime: number;
|
|
31
|
+
protected _endTime?: number;
|
|
32
|
+
|
|
33
|
+
protected _currentStep: number;
|
|
34
|
+
protected _percentage: number;
|
|
35
|
+
|
|
36
|
+
protected _isRunning: boolean;
|
|
37
|
+
protected _hasCompleted: boolean;
|
|
38
|
+
protected _hasFailed: boolean;
|
|
39
|
+
|
|
40
|
+
protected _promise: Promise<T>;
|
|
41
|
+
protected _publisher?: Publisher;
|
|
42
|
+
|
|
43
|
+
public constructor(executor: MaybeAsyncGeneratorFunction<undefined, T>, options?: LongRunningTaskOptions);
|
|
44
|
+
public constructor(executor: MaybeAsyncGeneratorFunction<number, T>, options?: LongRunningTaskOptions);
|
|
45
|
+
public constructor(executor: MaybeAsyncGeneratorFunction<number | undefined, T>, options?: LongRunningTaskOptions)
|
|
46
|
+
{
|
|
47
|
+
this._startTime = 0;
|
|
48
|
+
this._estimatedTime = 0;
|
|
49
|
+
|
|
50
|
+
this._currentStep = 0;
|
|
51
|
+
this._percentage = 0;
|
|
52
|
+
|
|
53
|
+
this._isRunning = true;
|
|
54
|
+
this._hasCompleted = false;
|
|
55
|
+
this._hasFailed = false;
|
|
56
|
+
|
|
57
|
+
const _onFulfilled = (result: T): T =>
|
|
58
|
+
{
|
|
59
|
+
this._estimatedTime = 0;
|
|
60
|
+
this._endTime = Date.now();
|
|
61
|
+
|
|
62
|
+
this._percentage = 100;
|
|
63
|
+
|
|
64
|
+
this._isRunning = false;
|
|
65
|
+
this._hasCompleted = true;
|
|
66
|
+
|
|
67
|
+
return result;
|
|
68
|
+
};
|
|
69
|
+
const _onRejected = (reason: unknown): never =>
|
|
70
|
+
{
|
|
71
|
+
this._endTime = Date.now();
|
|
72
|
+
|
|
73
|
+
this._isRunning = false;
|
|
74
|
+
this._hasFailed = true;
|
|
75
|
+
|
|
76
|
+
throw reason;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
let _executor: PromiseExecutor<T>;
|
|
80
|
+
|
|
81
|
+
options = { ...LongRunningTask._DefaultOptions, ...options };
|
|
82
|
+
if ((options.trackProgress))
|
|
83
|
+
{
|
|
84
|
+
let _trackProgress: (steps: number | undefined) => void;
|
|
85
|
+
|
|
86
|
+
this._publisher = new Publisher();
|
|
87
|
+
|
|
88
|
+
if (options.totalSteps)
|
|
89
|
+
{
|
|
90
|
+
if (options.stepIncrement)
|
|
91
|
+
{
|
|
92
|
+
_trackProgress = (steps: number | undefined) =>
|
|
93
|
+
{
|
|
94
|
+
if (steps) { this._currentStep += steps; }
|
|
95
|
+
else { this._currentStep += options.stepIncrement!; }
|
|
96
|
+
|
|
97
|
+
this._percentage = (this._currentStep / options.totalSteps!) * 100;
|
|
98
|
+
|
|
99
|
+
const elapsedTime = Date.now() - this._startTime;
|
|
100
|
+
const remainingSteps = options.totalSteps! - this._currentStep;
|
|
101
|
+
this._estimatedTime = (elapsedTime / this._currentStep) * remainingSteps;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
else
|
|
105
|
+
{
|
|
106
|
+
_trackProgress = (steps: number | undefined) =>
|
|
107
|
+
{
|
|
108
|
+
if (steps)
|
|
109
|
+
{
|
|
110
|
+
this._currentStep += steps;
|
|
111
|
+
this._percentage = (this._currentStep / options.totalSteps!) * 100;
|
|
112
|
+
|
|
113
|
+
const elapsedTime = Date.now() - this._startTime;
|
|
114
|
+
const remainingSteps = options.totalSteps! - this._currentStep;
|
|
115
|
+
this._estimatedTime = (elapsedTime / this._currentStep) * remainingSteps;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else if (options.stepIncrement)
|
|
121
|
+
{
|
|
122
|
+
_trackProgress = (steps: number | undefined) =>
|
|
123
|
+
{
|
|
124
|
+
if (steps) { this._currentStep += steps; }
|
|
125
|
+
else { this._currentStep += options.stepIncrement!; }
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
else
|
|
129
|
+
{
|
|
130
|
+
_trackProgress = (steps: number | undefined) =>
|
|
131
|
+
{
|
|
132
|
+
if (steps) { this._currentStep += steps; }
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (options.ignoreErrors)
|
|
137
|
+
{
|
|
138
|
+
_executor = async (resolve) =>
|
|
139
|
+
{
|
|
140
|
+
const generator = executor();
|
|
141
|
+
this._startTime = Date.now();
|
|
142
|
+
|
|
143
|
+
while (true)
|
|
144
|
+
{
|
|
145
|
+
try
|
|
146
|
+
{
|
|
147
|
+
const { done, value } = await generator.next();
|
|
148
|
+
|
|
149
|
+
if (done) { return resolve(value); }
|
|
150
|
+
else { _trackProgress(value); }
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// eslint-disable-next-line no-console
|
|
154
|
+
catch (error) { console.error(error); }
|
|
155
|
+
|
|
156
|
+
this._publisher!.publish("progress");
|
|
157
|
+
|
|
158
|
+
await yieldToEventLoop();
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
else
|
|
163
|
+
{
|
|
164
|
+
_executor = async (resolve, reject) =>
|
|
165
|
+
{
|
|
166
|
+
try
|
|
167
|
+
{
|
|
168
|
+
const generator = executor();
|
|
169
|
+
this._startTime = Date.now();
|
|
170
|
+
|
|
171
|
+
while (true)
|
|
172
|
+
{
|
|
173
|
+
const { done, value } = await generator.next();
|
|
174
|
+
if (done) { return resolve(value); }
|
|
175
|
+
else { _trackProgress(value); }
|
|
176
|
+
|
|
177
|
+
this._publisher!.publish("progress");
|
|
178
|
+
|
|
179
|
+
await yieldToEventLoop();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch (error) { reject(error); }
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
else if (options.ignoreErrors)
|
|
187
|
+
{
|
|
188
|
+
_executor = async (resolve) =>
|
|
189
|
+
{
|
|
190
|
+
const generator = executor();
|
|
191
|
+
this._startTime = Date.now();
|
|
192
|
+
|
|
193
|
+
while (true)
|
|
194
|
+
{
|
|
195
|
+
try
|
|
196
|
+
{
|
|
197
|
+
const { done, value } = await generator.next();
|
|
198
|
+
if (done) { return resolve(value); }
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// eslint-disable-next-line no-console
|
|
202
|
+
catch (error) { console.error(error); }
|
|
203
|
+
|
|
204
|
+
await yieldToEventLoop();
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
else
|
|
209
|
+
{
|
|
210
|
+
_executor = async (resolve, reject) =>
|
|
211
|
+
{
|
|
212
|
+
try
|
|
213
|
+
{
|
|
214
|
+
const generator = executor();
|
|
215
|
+
this._startTime = Date.now();
|
|
216
|
+
|
|
217
|
+
while (true)
|
|
218
|
+
{
|
|
219
|
+
const { done, value } = await generator.next();
|
|
220
|
+
if (done) { return resolve(value); }
|
|
221
|
+
|
|
222
|
+
await yieldToEventLoop();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
catch (error) { reject(error); }
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
this._promise = new Promise(_executor)
|
|
230
|
+
.then(_onFulfilled, _onRejected);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
public get startTime(): number { return this._startTime; }
|
|
234
|
+
public get elapsedTime(): number
|
|
235
|
+
{
|
|
236
|
+
if (this._isRunning) { return Date.now() - this._startTime; }
|
|
237
|
+
|
|
238
|
+
return this._endTime! - this._startTime;
|
|
239
|
+
}
|
|
240
|
+
public get estimatedTime(): number { return this._estimatedTime; }
|
|
241
|
+
public get endTime(): number
|
|
242
|
+
{
|
|
243
|
+
if (this._isRunning)
|
|
244
|
+
{
|
|
245
|
+
throw new RuntimeException("The task is still running and has no end time yet.");
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return this._endTime!;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
public get currentStep(): number { return this._currentStep; }
|
|
252
|
+
public get percentage(): number { return this._percentage; }
|
|
253
|
+
|
|
254
|
+
public get isRunning(): boolean { return this._isRunning; }
|
|
255
|
+
public get hasCompleted(): boolean { return this._hasCompleted; }
|
|
256
|
+
public get hasFailed(): boolean { return this._hasFailed; }
|
|
257
|
+
|
|
258
|
+
public then(onFulfilled?: null): Promise<T>;
|
|
259
|
+
public then<F = T>(onFulfilled: FulfilledHandler<T, F>, onRejected?: null): Promise<F>;
|
|
260
|
+
public then<F = T, R = never>(onFulfilled: FulfilledHandler<T, F>, onRejected: RejectedHandler<unknown, R>)
|
|
261
|
+
: Promise<F | R>;
|
|
262
|
+
public then<F = T, R = never>(
|
|
263
|
+
onFulfilled?: FulfilledHandler<T, F> | null,
|
|
264
|
+
onRejected?: RejectedHandler<unknown, R> | null): Promise<F | R>
|
|
265
|
+
{
|
|
266
|
+
return this._promise.then(onFulfilled, onRejected);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
public catch(onRejected?: null): Promise<T>;
|
|
270
|
+
public catch<R = never>(onRejected: RejectedHandler<unknown, R>): Promise<T | R>;
|
|
271
|
+
public catch<R = never>(onRejected?: RejectedHandler<unknown, R> | null): Promise<T | R>
|
|
272
|
+
{
|
|
273
|
+
return this._promise.catch(onRejected);
|
|
274
|
+
}
|
|
275
|
+
public finally(onFinally?: (() => void) | null): Promise<T>
|
|
276
|
+
{
|
|
277
|
+
return this._promise.finally(onFinally);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
public onProgress(callback: () => void): () => void
|
|
281
|
+
{
|
|
282
|
+
if (!(this._publisher))
|
|
283
|
+
{
|
|
284
|
+
throw new RuntimeException(
|
|
285
|
+
"You cannot subscribe to progress events without enabling progress tracking. " +
|
|
286
|
+
"Did you forget to set the `trackProgress` option to `true` when creating the task?"
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return this._publisher.subscribe("progress", callback);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
public readonly [Symbol.toStringTag]: string = "LongRunningTask";
|
|
294
|
+
}
|
|
@@ -2,6 +2,11 @@ import type { FulfilledHandler, PromiseExecutor, RejectedHandler } from "./types
|
|
|
2
2
|
|
|
3
3
|
export default class SmartPromise<T = void> implements Promise<T>
|
|
4
4
|
{
|
|
5
|
+
public static FromPromise<T>(promise: Promise<T>): SmartPromise<T>
|
|
6
|
+
{
|
|
7
|
+
return new SmartPromise((resolve, reject) => promise.then(resolve, reject));
|
|
8
|
+
}
|
|
9
|
+
|
|
5
10
|
protected _isPending: boolean;
|
|
6
11
|
protected _isFulfilled: boolean;
|
|
7
12
|
protected _isRejected: boolean;
|
|
@@ -59,5 +64,5 @@ export default class SmartPromise<T = void> implements Promise<T>
|
|
|
59
64
|
return this._promise.finally(onFinally);
|
|
60
65
|
}
|
|
61
66
|
|
|
62
|
-
public
|
|
67
|
+
public readonly [Symbol.toStringTag]: string = "SmartPromise";
|
|
63
68
|
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
export default class Thenable<T> implements Promise<T>
|
|
2
|
+
{
|
|
3
|
+
protected _onFulfilled: (result: T) => T;
|
|
4
|
+
protected _resolve(result: T): T
|
|
5
|
+
{
|
|
6
|
+
return this._onFulfilled(result);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
public constructor()
|
|
10
|
+
{
|
|
11
|
+
this._onFulfilled = (result: T) => result;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public then(onFulfilled?: null): Thenable<T>;
|
|
15
|
+
public then<F = T>(onFulfilled: (result: T) => F, onRejected?: null): Thenable<F>;
|
|
16
|
+
public then<F = T, R = never>(onFulfilled: (result: T) => F, onRejected: (reason: unknown) => R)
|
|
17
|
+
: Thenable<F | R>;
|
|
18
|
+
public then<F = T, R = never>(onFulfilled?: ((result: T) => F) | null, onRejected?: ((reason: unknown) => R) | null)
|
|
19
|
+
: Thenable<F | R>
|
|
20
|
+
{
|
|
21
|
+
if (onRejected)
|
|
22
|
+
{
|
|
23
|
+
const _previousOnFulfilled = this._onFulfilled;
|
|
24
|
+
this._onFulfilled = (result: T) =>
|
|
25
|
+
{
|
|
26
|
+
try
|
|
27
|
+
{
|
|
28
|
+
result = _previousOnFulfilled(result);
|
|
29
|
+
|
|
30
|
+
return (onFulfilled!(result) as unknown) as T;
|
|
31
|
+
}
|
|
32
|
+
catch (error)
|
|
33
|
+
{
|
|
34
|
+
return (onRejected(error) as unknown) as T;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
else if (onFulfilled)
|
|
39
|
+
{
|
|
40
|
+
const _previousOnFulfilled = this._onFulfilled;
|
|
41
|
+
this._onFulfilled = (result: T) =>
|
|
42
|
+
{
|
|
43
|
+
result = _previousOnFulfilled(result);
|
|
44
|
+
|
|
45
|
+
return (onFulfilled(result) as unknown) as T;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return (this as unknown) as Thenable<F | R>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public catch(onRejected?: null): Thenable<T>;
|
|
53
|
+
public catch<R = never>(onRejected: (reason: unknown) => R): Thenable<T | R>;
|
|
54
|
+
public catch<R = never>(onRejected?: ((reason: unknown) => R) | null): Thenable<T | R>
|
|
55
|
+
{
|
|
56
|
+
if (onRejected)
|
|
57
|
+
{
|
|
58
|
+
const _previousOnFulfilled = this._onFulfilled;
|
|
59
|
+
this._onFulfilled = (result) =>
|
|
60
|
+
{
|
|
61
|
+
try
|
|
62
|
+
{
|
|
63
|
+
return _previousOnFulfilled(result);
|
|
64
|
+
}
|
|
65
|
+
catch (error)
|
|
66
|
+
{
|
|
67
|
+
return (onRejected(error) as unknown) as T;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return this as Thenable<T | R>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public finally(onFinally?: (() => void) | null): Thenable<T>
|
|
76
|
+
{
|
|
77
|
+
if (onFinally)
|
|
78
|
+
{
|
|
79
|
+
const _previousOnFulfilled = this._onFulfilled;
|
|
80
|
+
this._onFulfilled = (result) =>
|
|
81
|
+
{
|
|
82
|
+
try
|
|
83
|
+
{
|
|
84
|
+
return _previousOnFulfilled(result);
|
|
85
|
+
}
|
|
86
|
+
finally
|
|
87
|
+
{
|
|
88
|
+
onFinally();
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return this;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public readonly [Symbol.toStringTag]: string = "Thenable";
|
|
97
|
+
}
|