@byloth/core 2.1.4 → 2.1.6

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.
@@ -893,7 +893,7 @@ export default class SmartIterator<T, R = void, N = undefined> implements Iterat
893
893
  *
894
894
  * for (const value of iterator)
895
895
  * {
896
- * if (value > 5) { break; } // Closing the iterator...
896
+ * if (value > 5) { break; } // "Closing the iterator..."
897
897
  *
898
898
  * console.log(value); // 1, 2, 3, 4, 5
899
899
  * }
@@ -1,5 +1,6 @@
1
1
  import DeferredPromise from "./deferred-promise.js";
2
+ import PromiseQueue from "./promise-queue.js";
2
3
  import SmartPromise from "./smart-promise.js";
3
4
  import TimedPromise from "./timed-promise.js";
4
5
 
5
- export { DeferredPromise, SmartPromise, TimedPromise };
6
+ export { DeferredPromise, PromiseQueue, SmartPromise, TimedPromise };
@@ -0,0 +1,222 @@
1
+ import type { Callback } from "../callbacks/types.js";
2
+
3
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
4
+ import { TimeoutException, ValueException } from "../exceptions/index.js";
5
+
6
+ import DeferredPromise from "./deferred-promise.js";
7
+ import SmartPromise from "./smart-promise.js";
8
+ import TimedPromise from "./timed-promise.js";
9
+ import type { MaybePromise, PromiseRejecter, PromiseResolver } from "./types.js";
10
+
11
+ /**
12
+ * A class that represents a queue of asynchronous operations, allowing them to be executed sequentially.
13
+ *
14
+ * It extends the {@link SmartPromise} class, providing a way to manage multiple promises in a controlled manner.
15
+ * This class is useful for scenarios where you need to ensure
16
+ * that only one asynchronous operation is executed at a time,
17
+ * such as when dealing with API requests, file operations or any other
18
+ * asynchronous tasks that need to be handled in a specific order.
19
+ *
20
+ * ---
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * const queue = new PromiseQueue();
25
+ *
26
+ * queue.enqueue(() => new Promise((resolve) => setTimeout(() => resolve("First"), 2000)))
27
+ * queue.enqueue(() => new Promise((resolve) => setTimeout(() => resolve("Second"), 500)))
28
+ * queue.enqueue(() => new Promise((resolve) => setTimeout(() => resolve("Third"), 1000)))
29
+ *
30
+ * await queue; // "First", "Second", "Third"
31
+ * ```
32
+ */
33
+ export default class PromiseQueue extends SmartPromise<void>
34
+ {
35
+ /**
36
+ * The number of promises currently in the queue.
37
+ */
38
+ protected _count: number;
39
+
40
+ /**
41
+ * A flag indicating whether the promise is still pending or not.
42
+ */
43
+ public override get isPending(): boolean
44
+ {
45
+ return this._count > 0;
46
+ }
47
+ /**
48
+ * A flag indicating whether the promise has been fulfilled or not.
49
+ */
50
+ public override get isFulfilled(): boolean
51
+ {
52
+ return this._count === 0;
53
+ }
54
+
55
+ /**
56
+ * A flag indicating whether the promise has been rejected or not.
57
+ *
58
+ * Please note the {@link PromiseQueue} doesn't support rejection states.
59
+ * Accessing this property will always result in a {@link ValueException}.
60
+ */
61
+ public override get isRejected(): never
62
+ {
63
+ throw new ValueException("`PromiseQueue` doesn't support rejection states.");
64
+ }
65
+
66
+ /**
67
+ * The native {@link Promise} object wrapped by this instance.
68
+ */
69
+ declare protected _promise: Promise<void>;
70
+
71
+ /**
72
+ * Initializes a new instance of the {@link PromiseQueue} class.
73
+ */
74
+ public constructor()
75
+ {
76
+ super((resolve) => resolve());
77
+
78
+ this._count = 0;
79
+
80
+ this._isPending = false;
81
+ this._isFulfilled = false;
82
+ this._isRejected = false;
83
+ }
84
+
85
+ /**
86
+ * Enqueues a {@link DeferredPromise} into the queue.
87
+ *
88
+ * The promise will be executed in sequence after previously enqueued promises.
89
+ *
90
+ * ---
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * const queue = new PromiseQueue();
95
+ * const deferred = new DeferredPromise(() => console.log("Hello, world!"));
96
+ *
97
+ * queue.enqueue(deferred); // "Hello, world!"
98
+ * ```
99
+ *
100
+ * ---
101
+ *
102
+ * @template T The type of value the promise will eventually resolve to.
103
+ *
104
+ * @param promise A `DeferredPromise<void, T>` instance to enqueue.
105
+ *
106
+ * @returns A {@link Promise} that resolves to the value of the enqueued promise.
107
+ */
108
+ public enqueue<T>(promise: DeferredPromise<void, T>): Promise<T>;
109
+
110
+ /**
111
+ * Enqueues a {@link DeferredPromise} into the queue with an optional timeout.
112
+ *
113
+ * The promise will be executed in sequence after previously enqueued promises.
114
+ * If the promise takes longer than the specified timeout, it will be rejected with a {@link TimeoutException}.
115
+ *
116
+ * ---
117
+ *
118
+ * @example
119
+ * ```ts
120
+ * const queue = new PromiseQueue();
121
+ * const deferred = new DeferredPromise(() => console.log("Hello, world!"));
122
+ *
123
+ * queue.enqueue(deferred, 5000); // "Hello, world!"
124
+ * ```
125
+ *
126
+ * ---
127
+ *
128
+ * @template T The type of value the promise will eventually resolve to.
129
+ *
130
+ * @param promise A `DeferredPromise<void, T>` instance to enqueue.
131
+ * @param timeout The maximum time in milliseconds that the operation can take before timing out.
132
+ *
133
+ * @returns
134
+ * A {@link TimedPromise} that resolves to the value of the enqueued promise or rejects
135
+ * with a `TimeoutException` if the operation takes longer than the specified timeout.
136
+ */
137
+ public enqueue<T>(promise: DeferredPromise<void, T>, timeout: number): TimedPromise<T>;
138
+
139
+ /**
140
+ * Enqueues a callback that returns a {@link MaybePromise} value of type `T` into the queue.
141
+ *
142
+ * The executor will be executed in sequence after previously enqueued promises.
143
+ *
144
+ * ---
145
+ *
146
+ * @example
147
+ * ```ts
148
+ * const queue = new PromiseQueue();
149
+ *
150
+ * queue.enqueue(() => console.log("Hello, world!")); // "Hello, world!"
151
+ * ```
152
+ *
153
+ * ---
154
+ *
155
+ * @template T The type of value the promise will eventually resolve to.
156
+ *
157
+ * @param executor A callback that returns a `MaybePromise<T>` value to enqueue.
158
+ *
159
+ * @returns A {@link Promise} that resolves to the value of the enqueued executor.
160
+ */
161
+ public enqueue<T>(executor: Callback<[], MaybePromise<T>>): Promise<T>;
162
+
163
+ /**
164
+ * Enqueues a callback that returns a {@link MaybePromise}
165
+ * value of type `T` into the queue with an optional timeout.
166
+ *
167
+ * The executor will be executed in sequence after previously enqueued promises.
168
+ * If the executor takes longer than the specified timeout, it will be rejected with a {@link TimeoutException}.
169
+ *
170
+ * ---
171
+ *
172
+ * @example
173
+ * ```ts
174
+ * const queue = new PromiseQueue();
175
+ *
176
+ * queue.enqueue(() => console.log("Hello, world!"), 5000); // "Hello, world!"
177
+ * ```
178
+ *
179
+ * ---
180
+ *
181
+ * @template T The type of value the promise will eventually resolve to.
182
+ *
183
+ * @param executor A callback that returns a `MaybePromise<T>` value to enqueue.
184
+ * @param timeout The maximum time in milliseconds that the operation can take before timing out.
185
+ *
186
+ * @returns
187
+ * A {@link TimedPromise} that resolves to the value of the enqueued executor or rejects
188
+ * with a `TimeoutException` if the operation takes longer than the specified timeout.
189
+ */
190
+ public enqueue<T>(executor: Callback<[], MaybePromise<T>>, timeout?: number): TimedPromise<T>;
191
+ public enqueue<T>(executor: DeferredPromise<void, T> | Callback<[], MaybePromise<T>>, timeout?: number)
192
+ : Promise<T> | TimedPromise<T>
193
+ {
194
+ this._count += 1;
195
+
196
+ if (executor instanceof DeferredPromise)
197
+ {
198
+ const _executor = executor as DeferredPromise<void, T>;
199
+
200
+ executor = () =>
201
+ {
202
+ _executor.resolve();
203
+
204
+ return _executor;
205
+ };
206
+ }
207
+
208
+ const _executor = (resolve: PromiseResolver<T>, reject: PromiseRejecter) =>
209
+ {
210
+ this._promise = this._promise
211
+ .then(executor)
212
+ .then((value) => { this._count -= 1; resolve(value); })
213
+ .catch((value) => { this._count -= 1; reject(value); });
214
+ };
215
+
216
+ if (timeout) { return new TimedPromise<T>(_executor, timeout); }
217
+
218
+ return new Promise<T>(_executor);
219
+ }
220
+
221
+ public override readonly [Symbol.toStringTag]: string = "PromiseQueue";
222
+ }
@@ -24,9 +24,9 @@ interface ClockEventsMap
24
24
  * ```ts
25
25
  * const clock = new Clock();
26
26
  *
27
- * clock.onStart(() => { console.log("The clock has started."); });
28
- * clock.onTick((elapsedTime) => { console.log(`The clock has ticked at ${elapsedTime}ms.`); });
29
- * clock.onStop(() => { console.log("The clock has stopped."); });
27
+ * clock.onStart(() => console.log("The clock has started."));
28
+ * clock.onTick((elapsedTime) => console.log(`The clock has ticked at ${elapsedTime}ms.`));
29
+ * clock.onStop(() => console.log("The clock has stopped."));
30
30
  *
31
31
  * clock.start();
32
32
  * ```
@@ -30,10 +30,10 @@ interface CountdownEventsMap
30
30
  * ```ts
31
31
  * const countdown = new Countdown(10_000);
32
32
  *
33
- * countdown.onStart(() => { console.log("The countdown has started."); });
34
- * countdown.onTick((remainingTime) => { console.log(`The countdown has ${remainingTime}ms remaining.`); });
35
- * countdown.onStop((reason) => { console.log(`The countdown has stopped because of ${reason}.`); });
36
- * countdown.onExpire(() => { console.log("The countdown has expired."); });
33
+ * countdown.onStart(() => console.log("The countdown has started."));
34
+ * countdown.onTick((remainingTime) => console.log(`The countdown has ${remainingTime}ms remaining.`));
35
+ * countdown.onStop((reason) => console.log(`The countdown has stopped because of ${reason}.`));
36
+ * countdown.onExpire(() => console.log("The countdown has expired."));
37
37
  *
38
38
  * countdown.start();
39
39
  * ```
@@ -32,8 +32,8 @@ interface GameLoopEventsMap
32
32
  * console.log(`The game loop has been running for ${elapsedTime}ms.`);
33
33
  * });
34
34
  *
35
- * loop.onStart(() => { console.log("The game loop has started."); });
36
- * loop.onStop(() => { console.log("The game loop has stopped."); });
35
+ * loop.onStart(() => console.log("The game loop has started."));
36
+ * loop.onStop(() => console.log("The game loop has stopped."));
37
37
  *
38
38
  * loop.start();
39
39
  * ```
@@ -226,7 +226,7 @@ export default class GameLoop
226
226
  *
227
227
  * @example
228
228
  * ```ts
229
- * loop.onStart(() => { console.log("The game loop has started."); });
229
+ * loop.onStart(() => console.log("The game loop has started."));
230
230
  * ```
231
231
  *
232
232
  * ---
@@ -247,7 +247,7 @@ export default class GameLoop
247
247
  *
248
248
  * @example
249
249
  * ```ts
250
- * loop.onStop(() => { console.log("The game loop has stopped."); });
250
+ * loop.onStop(() => console.log("The game loop has stopped."));
251
251
  * ```
252
252
  *
253
253
  * ---
@@ -38,4 +38,12 @@ export type {
38
38
 
39
39
  } from "./promises/types.js";
40
40
 
41
- export type { Callback, CallbackMap, Publishable, Subscribable } from "./callbacks/types.js";
41
+ export type {
42
+ Callback,
43
+ CallbackMap,
44
+ InternalsEventsMap,
45
+ WildcardEventsMap,
46
+ Publishable,
47
+ Subscribable
48
+
49
+ } from "./callbacks/types.js";