@byloth/core 2.0.0-rc.9 → 2.0.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/core.js +3371 -608
- package/dist/core.js.map +1 -1
- package/dist/core.umd.cjs +2 -2
- package/dist/core.umd.cjs.map +1 -1
- package/package.json +13 -10
- package/src/core/types.ts +41 -0
- package/src/helpers.ts +11 -2
- package/src/index.ts +12 -9
- package/src/models/aggregators/aggregated-async-iterator.ts +765 -21
- package/src/models/aggregators/aggregated-iterator.ts +698 -22
- package/src/models/aggregators/reduced-iterator.ts +699 -10
- package/src/models/aggregators/types.ts +153 -10
- package/src/models/callbacks/callable-object.ts +42 -6
- package/src/models/callbacks/index.ts +2 -2
- package/src/models/callbacks/publisher.ts +139 -4
- package/src/models/callbacks/switchable-callback.ts +138 -4
- package/src/models/callbacks/types.ts +16 -0
- package/src/models/exceptions/core.ts +112 -3
- package/src/models/exceptions/index.ts +340 -13
- package/src/models/index.ts +4 -8
- package/src/models/iterators/smart-async-iterator.ts +687 -22
- package/src/models/iterators/smart-iterator.ts +631 -21
- package/src/models/iterators/types.ts +268 -9
- package/src/models/json/json-storage.ts +388 -110
- package/src/models/json/types.ts +10 -1
- package/src/models/promises/deferred-promise.ts +75 -5
- package/src/models/promises/index.ts +1 -3
- package/src/models/promises/smart-promise.ts +232 -4
- package/src/models/promises/timed-promise.ts +38 -1
- package/src/models/promises/types.ts +84 -2
- package/src/models/timers/clock.ts +91 -19
- package/src/models/timers/countdown.ts +152 -22
- package/src/models/timers/game-loop.ts +243 -0
- package/src/models/timers/index.ts +2 -1
- package/src/models/types.ts +6 -5
- package/src/utils/async.ts +43 -0
- package/src/utils/curve.ts +75 -0
- package/src/utils/date.ts +204 -10
- package/src/utils/dom.ts +16 -2
- package/src/utils/index.ts +3 -2
- package/src/utils/iterator.ts +200 -17
- package/src/utils/math.ts +55 -3
- package/src/utils/random.ts +109 -2
- package/src/utils/string.ts +11 -0
- package/src/models/game-loop.ts +0 -83
- package/src/models/promises/long-running-task.ts +0 -294
- package/src/models/promises/thenable.ts +0 -97
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import AggregatedAsyncIterator from "../aggregators/aggregated-async-iterator.js";
|
|
2
2
|
import { ValueException } from "../exceptions/index.js";
|
|
3
|
+
import type { MaybePromise } from "../types.js";
|
|
3
4
|
|
|
4
5
|
import type {
|
|
5
6
|
GeneratorFunction,
|
|
@@ -7,25 +8,147 @@ import type {
|
|
|
7
8
|
MaybeAsyncGeneratorFunction,
|
|
8
9
|
MaybeAsyncIteratee,
|
|
9
10
|
MaybeAsyncReducer,
|
|
10
|
-
|
|
11
|
-
MaybeAsyncIteratorLike,
|
|
12
|
-
MaybeAsyncTypeGuardIteratee
|
|
11
|
+
MaybeAsyncIteratorLike
|
|
13
12
|
|
|
14
13
|
} from "./types.js";
|
|
15
14
|
|
|
15
|
+
/**
|
|
16
|
+
* A wrapper class representing an enhanced and instantiable version
|
|
17
|
+
* of the native {@link AsyncIterable} & {@link AsyncIterator} interfaces.
|
|
18
|
+
*
|
|
19
|
+
* It provides a set of utility methods to better manipulate and transform
|
|
20
|
+
* asynchronous iterators in a functional and highly performant way.
|
|
21
|
+
* It takes inspiration from the native {@link Array} methods like
|
|
22
|
+
* {@link Array.map}, {@link Array.filter}, {@link Array.reduce}, etc...
|
|
23
|
+
*
|
|
24
|
+
* The class is lazy, meaning that the transformations are applied
|
|
25
|
+
* only when the resulting iterator is materialized, not before.
|
|
26
|
+
* This allows to chain multiple transformations without
|
|
27
|
+
* the need to iterate over the elements multiple times.
|
|
28
|
+
*
|
|
29
|
+
* ```ts
|
|
30
|
+
* const result = new SmartAsyncIterator<number>(["-5", "-4", "-3", "-2", "-1", "0", "1", "2", "3", "4", "5"])
|
|
31
|
+
* .map((value) => Number(value))
|
|
32
|
+
* .map((value) => value + Math.ceil(Math.abs(value / 2)))
|
|
33
|
+
* .filter((value) => value >= 0)
|
|
34
|
+
* .map((value) => value + 1)
|
|
35
|
+
* .reduce((acc, value) => acc + value);
|
|
36
|
+
*
|
|
37
|
+
* console.log(await result); // 31
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @template T The type of elements in the iterator.
|
|
41
|
+
* @template R The type of the final result of the iterator. Default is `void`.
|
|
42
|
+
* @template N The type of the argument passed to the `next` method. Default is `undefined`.
|
|
43
|
+
*/
|
|
16
44
|
export default class SmartAsyncIterator<T, R = void, N = undefined> implements AsyncIterator<T, R, N>
|
|
17
45
|
{
|
|
46
|
+
/**
|
|
47
|
+
* The native {@link AsyncIterator} object that is being wrapped by this instance.
|
|
48
|
+
*/
|
|
18
49
|
protected _iterator: AsyncIterator<T, R, N>;
|
|
19
50
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Initializes a new instance of the {@link SmartAsyncIterator} class.
|
|
53
|
+
*
|
|
54
|
+
* ```ts
|
|
55
|
+
* const iterator = new SmartAsyncIterator<string>(["A", "B", "C"]);
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @param iterable The iterable object to wrap.
|
|
59
|
+
*/
|
|
23
60
|
public constructor(iterable: Iterable<T>);
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Initializes a new instance of the {@link SmartAsyncIterator} class.
|
|
64
|
+
*
|
|
65
|
+
* ```ts
|
|
66
|
+
* const iterator = new SmartAsyncIterator<number>([1, 2, 3, 4, 5]);
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* @param iterable The asynchronous iterable object to wrap.
|
|
70
|
+
*/
|
|
24
71
|
public constructor(iterable: AsyncIterable<T>);
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Initializes a new instance of the {@link SmartAsyncIterator} class.
|
|
75
|
+
*
|
|
76
|
+
* ```ts
|
|
77
|
+
* const iterator = new SmartAsyncIterator<number, void, number>({
|
|
78
|
+
* _sum: 0, _count: 0,
|
|
79
|
+
*
|
|
80
|
+
* next: function(value: number)
|
|
81
|
+
* {
|
|
82
|
+
* this._sum += value;
|
|
83
|
+
* this._count += 1;
|
|
84
|
+
*
|
|
85
|
+
* return { done: false, value: this._sum / this._count };
|
|
86
|
+
* }
|
|
87
|
+
* })
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* @param iterator The iterator object to wrap.
|
|
91
|
+
*/
|
|
25
92
|
public constructor(iterator: Iterator<T, R, N>);
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Initializes a new instance of the {@link SmartAsyncIterator} class.
|
|
96
|
+
*
|
|
97
|
+
* ```ts
|
|
98
|
+
* const iterator = new SmartAsyncIterator<number, void, number>({
|
|
99
|
+
* _sum: 0, _count: 0,
|
|
100
|
+
*
|
|
101
|
+
* next: async function(value: number)
|
|
102
|
+
* {
|
|
103
|
+
* this._sum += value;
|
|
104
|
+
* this._count += 1;
|
|
105
|
+
*
|
|
106
|
+
* return { done: false, value: this._sum / this._count };
|
|
107
|
+
* }
|
|
108
|
+
* })
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* @param iterator The asynchronous iterator object to wrap.
|
|
112
|
+
*/
|
|
26
113
|
public constructor(iterator: AsyncIterator<T, R, N>);
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Initializes a new instance of the {@link SmartAsyncIterator} class.
|
|
117
|
+
*
|
|
118
|
+
* ```ts
|
|
119
|
+
* const iterator = new SmartAsyncIterator<number>(function* ()
|
|
120
|
+
* {
|
|
121
|
+
* for (let i = 2; i < 65_536; i *= 2) { yield (i - 1); }
|
|
122
|
+
* });
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
125
|
+
* @param generatorFn The generator function to wrap.
|
|
126
|
+
*/
|
|
27
127
|
public constructor(generatorFn: GeneratorFunction<T, R, N>);
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Initializes a new instance of the {@link SmartAsyncIterator} class.
|
|
131
|
+
*
|
|
132
|
+
* ```ts
|
|
133
|
+
* const iterator = new SmartAsyncIterator<number>(async function* ()
|
|
134
|
+
* {
|
|
135
|
+
* for await (let i = 2; i < 65_536; i *= 2) { yield (i - 1); }
|
|
136
|
+
* });
|
|
137
|
+
* ```
|
|
138
|
+
*
|
|
139
|
+
* @param generatorFn The asynchronous generator function to wrap.
|
|
140
|
+
*/
|
|
28
141
|
public constructor(generatorFn: AsyncGeneratorFunction<T, R, N>);
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Initializes a new instance of the {@link SmartAsyncIterator} class.
|
|
145
|
+
*
|
|
146
|
+
* ```ts
|
|
147
|
+
* const iterator = new SmartAsyncIterator(values);
|
|
148
|
+
* ```
|
|
149
|
+
*
|
|
150
|
+
* @param argument The synchronous or asynchronous iterable, iterator or generator function to wrap.
|
|
151
|
+
*/
|
|
29
152
|
public constructor(argument: MaybeAsyncIteratorLike<T, R, N> | MaybeAsyncGeneratorFunction<T, R, N>);
|
|
30
153
|
public constructor(argument: MaybeAsyncIteratorLike<T, R, N> | MaybeAsyncGeneratorFunction<T, R, N>)
|
|
31
154
|
{
|
|
@@ -88,11 +211,33 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
88
211
|
|
|
89
212
|
})();
|
|
90
213
|
}
|
|
91
|
-
|
|
92
|
-
if (this._iterator.return) { this.return = (value?: R) => this._iterator.return!(value); }
|
|
93
|
-
if (this._iterator.throw) { this.throw = (error?: unknown) => this._iterator.throw!(error); }
|
|
94
214
|
}
|
|
95
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Determines whether all elements of the iterator satisfy a given condition.
|
|
218
|
+
* See also {@link SmartAsyncIterator.some}.
|
|
219
|
+
*
|
|
220
|
+
* This method will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
221
|
+
* Once a single element doesn't satisfy the condition, the method will return `false` immediately.
|
|
222
|
+
*
|
|
223
|
+
* This may lead to an unknown final state of the iterator, which may be entirely or partially consumed.
|
|
224
|
+
* For this reason, it's recommended to consider it as consumed in any case and to not use it anymore.
|
|
225
|
+
* Consider using {@link SmartAsyncIterator.find} instead.
|
|
226
|
+
*
|
|
227
|
+
* If the iterator is infinite and every element satisfies the condition, the method will never return.
|
|
228
|
+
*
|
|
229
|
+
* ```ts
|
|
230
|
+
* const iterator = new SmartAsyncIterator<number>([-2, -1, 0, 1, 2]);
|
|
231
|
+
* const result = await iterator.every(async (value) => value < 0);
|
|
232
|
+
*
|
|
233
|
+
* console.log(result); // false
|
|
234
|
+
* ```
|
|
235
|
+
*
|
|
236
|
+
* @param predicate The condition to check for each element of the iterator.
|
|
237
|
+
*
|
|
238
|
+
* @returns
|
|
239
|
+
* A {@link Promise} that will resolve to `true` if all elements satisfy the condition, `false` otherwise.
|
|
240
|
+
*/
|
|
96
241
|
public async every(predicate: MaybeAsyncIteratee<T, boolean>): Promise<boolean>
|
|
97
242
|
{
|
|
98
243
|
let index = 0;
|
|
@@ -107,6 +252,32 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
107
252
|
index += 1;
|
|
108
253
|
}
|
|
109
254
|
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Determines whether any element of the iterator satisfies a given condition.
|
|
258
|
+
* See also {@link SmartAsyncIterator.every}.
|
|
259
|
+
*
|
|
260
|
+
* This method will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
261
|
+
* Once a single element satisfies the condition, the method will return `true` immediately.
|
|
262
|
+
*
|
|
263
|
+
* This may lead to an unknown final state of the iterator, which may be entirely or partially consumed.
|
|
264
|
+
* For this reason, it's recommended to consider it as consumed in any case and to not use it anymore.
|
|
265
|
+
* Consider using {@link SmartAsyncIterator.find} instead.
|
|
266
|
+
*
|
|
267
|
+
* If the iterator is infinite and no element satisfies the condition, the method will never return.
|
|
268
|
+
*
|
|
269
|
+
* ```ts
|
|
270
|
+
* const iterator = new SmartAsyncIterator<number>([-2, -1, 0, 1, 2]);
|
|
271
|
+
* const result = await iterator.some(async (value) => value > 0);
|
|
272
|
+
*
|
|
273
|
+
* console.log(result); // true
|
|
274
|
+
* ```
|
|
275
|
+
*
|
|
276
|
+
* @param predicate The condition to check for each element of the iterator.
|
|
277
|
+
*
|
|
278
|
+
* @returns
|
|
279
|
+
* A {@link Promise} that will resolve to `true` if any element satisfies the condition, `false` otherwise.
|
|
280
|
+
*/
|
|
110
281
|
public async some(predicate: MaybeAsyncIteratee<T, boolean>): Promise<boolean>
|
|
111
282
|
{
|
|
112
283
|
let index = 0;
|
|
@@ -122,8 +293,63 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
122
293
|
}
|
|
123
294
|
}
|
|
124
295
|
|
|
296
|
+
/**
|
|
297
|
+
* Filters the elements of the iterator using a given condition.
|
|
298
|
+
*
|
|
299
|
+
* This method will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
300
|
+
* If the condition is met, the element will be included in the new iterator.
|
|
301
|
+
*
|
|
302
|
+
* Since the iterator is lazy, the filtering process will
|
|
303
|
+
* be executed once the resulting iterator is materialized.
|
|
304
|
+
*
|
|
305
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
306
|
+
* This means that the original iterator won't be consumed until the
|
|
307
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
308
|
+
*
|
|
309
|
+
* ```ts
|
|
310
|
+
* const iterator = new SmartAsyncIterator<number>([-2, -1, 0, 1, 2]);
|
|
311
|
+
* const result = iterator.filter(async (value) => value < 0);
|
|
312
|
+
*
|
|
313
|
+
* console.log(await result.toArray()); // [-2, -1]
|
|
314
|
+
* ```
|
|
315
|
+
*
|
|
316
|
+
* @param predicate The condition to check for each element of the iterator.
|
|
317
|
+
*
|
|
318
|
+
* @returns A new {@link SmartAsyncIterator} containing only the elements that satisfy the condition.
|
|
319
|
+
*/
|
|
125
320
|
public filter(predicate: MaybeAsyncIteratee<T, boolean>): SmartAsyncIterator<T, R>;
|
|
126
|
-
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Filters the elements of the iterator using a given condition.
|
|
324
|
+
*
|
|
325
|
+
* This method will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
326
|
+
* If the condition is met, the element will be included in the new iterator.
|
|
327
|
+
*
|
|
328
|
+
* Since the iterator is lazy, the filtering process will
|
|
329
|
+
* be executed once the resulting iterator is materialized.
|
|
330
|
+
*
|
|
331
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
332
|
+
* This means that the original iterator won't be consumed until the
|
|
333
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
334
|
+
*
|
|
335
|
+
* ```ts
|
|
336
|
+
* const iterator = new SmartAsyncIterator<number | string>([-2, "-1", "0", 1, "2"]);
|
|
337
|
+
* const result = iterator.filter<number>(async (value) => typeof value === "number");
|
|
338
|
+
*
|
|
339
|
+
* console.log(await result.toArray()); // [-2, 1]
|
|
340
|
+
* ```
|
|
341
|
+
*
|
|
342
|
+
* @template S
|
|
343
|
+
* The type of the elements that satisfy the condition.
|
|
344
|
+
* This allows the type-system to infer the correct type of the new iterator.
|
|
345
|
+
*
|
|
346
|
+
* It must be a subtype of the original type of the elements.
|
|
347
|
+
*
|
|
348
|
+
* @param predicate The type guard condition to check for each element of the iterator.
|
|
349
|
+
*
|
|
350
|
+
* @returns A new {@link SmartAsyncIterator} containing only the elements that satisfy the condition.
|
|
351
|
+
*/
|
|
352
|
+
public filter<S extends T>(predicate: MaybeAsyncIteratee<T, boolean>): SmartAsyncIterator<S, R>;
|
|
127
353
|
public filter(predicate: MaybeAsyncIteratee<T, boolean>): SmartAsyncIterator<T, R>
|
|
128
354
|
{
|
|
129
355
|
const iterator = this._iterator;
|
|
@@ -131,11 +357,9 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
131
357
|
return new SmartAsyncIterator<T, R>(async function* ()
|
|
132
358
|
{
|
|
133
359
|
let index = 0;
|
|
134
|
-
|
|
135
360
|
while (true)
|
|
136
361
|
{
|
|
137
362
|
const result = await iterator.next();
|
|
138
|
-
|
|
139
363
|
if (result.done) { return result.value; }
|
|
140
364
|
if (await predicate(result.value, index)) { yield result.value; }
|
|
141
365
|
|
|
@@ -143,6 +367,33 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
143
367
|
}
|
|
144
368
|
});
|
|
145
369
|
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Maps the elements of the iterator using a given transformation function.
|
|
373
|
+
*
|
|
374
|
+
* This method will iterate over all elements of the iterator applying the transformation function.
|
|
375
|
+
* The result of each transformation will be included in the new iterator.
|
|
376
|
+
*
|
|
377
|
+
* Since the iterator is lazy, the mapping process will
|
|
378
|
+
* be executed once the resulting iterator is materialized.
|
|
379
|
+
*
|
|
380
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
381
|
+
* This means that the original iterator won't be consumed until the
|
|
382
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
383
|
+
*
|
|
384
|
+
* ```ts
|
|
385
|
+
* const iterator = new SmartAsyncIterator<number>([-2, -1, 0, 1, 2]);
|
|
386
|
+
* const result = iterator.map(async (value) => Math.abs(value));
|
|
387
|
+
*
|
|
388
|
+
* console.log(await result.toArray()); // [2, 1, 0, 1, 2]
|
|
389
|
+
* ```
|
|
390
|
+
*
|
|
391
|
+
* @template V The type of the elements after the transformation.
|
|
392
|
+
*
|
|
393
|
+
* @param iteratee The transformation function to apply to each element of the iterator.
|
|
394
|
+
*
|
|
395
|
+
* @returns A new {@link SmartAsyncIterator} containing the transformed elements.
|
|
396
|
+
*/
|
|
146
397
|
public map<V>(iteratee: MaybeAsyncIteratee<T, V>): SmartAsyncIterator<V, R>
|
|
147
398
|
{
|
|
148
399
|
const iterator = this._iterator;
|
|
@@ -150,7 +401,6 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
150
401
|
return new SmartAsyncIterator<V, R>(async function* ()
|
|
151
402
|
{
|
|
152
403
|
let index = 0;
|
|
153
|
-
|
|
154
404
|
while (true)
|
|
155
405
|
{
|
|
156
406
|
const result = await iterator.next();
|
|
@@ -162,7 +412,60 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
162
412
|
}
|
|
163
413
|
});
|
|
164
414
|
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Reduces the elements of the iterator using a given reducer function.
|
|
418
|
+
* This method will consume the entire iterator in the process.
|
|
419
|
+
*
|
|
420
|
+
* It will iterate over all elements of the iterator applying the reducer function.
|
|
421
|
+
* The result of each iteration will be passed as the accumulator to the next one.
|
|
422
|
+
*
|
|
423
|
+
* The first accumulator value will be the first element of the iterator.
|
|
424
|
+
* The last accumulator value will be the final result of the reduction.
|
|
425
|
+
*
|
|
426
|
+
* Also note that:
|
|
427
|
+
* - If an empty iterator is provided, a {@link ValueException} will be thrown.
|
|
428
|
+
* - If the iterator is infinite, the method will never return.
|
|
429
|
+
*
|
|
430
|
+
* ```ts
|
|
431
|
+
* const iterator = new SmartAsyncIterator<number>([1, 2, 3, 4, 5]);
|
|
432
|
+
* const result = await iterator.reduce(async (acc, value) => acc + value);
|
|
433
|
+
*
|
|
434
|
+
* console.log(result); // 15
|
|
435
|
+
* ```
|
|
436
|
+
*
|
|
437
|
+
* @param reducer The reducer function to apply to each element of the iterator.
|
|
438
|
+
*
|
|
439
|
+
* @returns A {@link Promise} that will resolve to the final result of the reduction.
|
|
440
|
+
*/
|
|
165
441
|
public async reduce(reducer: MaybeAsyncReducer<T, T>): Promise<T>;
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Reduces the elements of the iterator using a given reducer function.
|
|
445
|
+
* This method will consume the entire iterator in the process.
|
|
446
|
+
*
|
|
447
|
+
* It will iterate over all elements of the iterator applying the reducer function.
|
|
448
|
+
* The result of each iteration will be passed as the accumulator to the next one.
|
|
449
|
+
*
|
|
450
|
+
* The first accumulator value will be the provided initial value.
|
|
451
|
+
* The last accumulator value will be the final result of the reduction.
|
|
452
|
+
*
|
|
453
|
+
* If the iterator is infinite, the method will never return.
|
|
454
|
+
*
|
|
455
|
+
* ```ts
|
|
456
|
+
* const iterator = new SmartAsyncIterator<number>([1, 2, 3, 4, 5]);
|
|
457
|
+
* const result = await iterator.reduce(async (acc, value) => acc + value, 10);
|
|
458
|
+
*
|
|
459
|
+
* console.log(result); // 25
|
|
460
|
+
* ```
|
|
461
|
+
*
|
|
462
|
+
* @template A The type of the accumulator value which will also be the type of the final result of the reduction.
|
|
463
|
+
*
|
|
464
|
+
* @param reducer The reducer function to apply to each element of the iterator.
|
|
465
|
+
* @param initialValue The initial value of the accumulator.
|
|
466
|
+
*
|
|
467
|
+
* @returns A {@link Promise} that will resolve to the final result of the reduction.
|
|
468
|
+
*/
|
|
166
469
|
public async reduce<A>(reducer: MaybeAsyncReducer<T, A>, initialValue: A): Promise<A>;
|
|
167
470
|
public async reduce<A>(reducer: MaybeAsyncReducer<T, A>, initialValue?: A): Promise<A>
|
|
168
471
|
{
|
|
@@ -188,31 +491,82 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
188
491
|
}
|
|
189
492
|
}
|
|
190
493
|
|
|
191
|
-
|
|
494
|
+
/**
|
|
495
|
+
* Flattens the elements of the iterator using a given transformation function.
|
|
496
|
+
*
|
|
497
|
+
* This method will iterate over all elements of the iterator applying the transformation function.
|
|
498
|
+
* The result of each transformation will be flattened and included in the new iterator.
|
|
499
|
+
*
|
|
500
|
+
* Since the iterator is lazy, the flattening process will
|
|
501
|
+
* be executed once the resulting iterator is materialized.
|
|
502
|
+
*
|
|
503
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
504
|
+
* This means that the original iterator won't be consumed until the
|
|
505
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
506
|
+
*
|
|
507
|
+
* ```ts
|
|
508
|
+
* const iterator = new SmartAsyncIterator<number[]>([[-2, -1], 0, 1, 2, [3, 4, 5]]);
|
|
509
|
+
* const result = iterator.flatMap(async (value) => value);
|
|
510
|
+
*
|
|
511
|
+
* console.log(await result.toArray()); // [-2, -1, 0, 1, 2, 3, 4, 5]
|
|
512
|
+
* ```
|
|
513
|
+
*
|
|
514
|
+
* @template V The type of the elements after the transformation.
|
|
515
|
+
*
|
|
516
|
+
* @param iteratee The transformation function to apply to each element of the iterator.
|
|
517
|
+
*
|
|
518
|
+
* @returns A new {@link SmartAsyncIterator} containing the flattened elements.
|
|
519
|
+
*/
|
|
520
|
+
public flatMap<V>(iteratee: MaybeAsyncIteratee<T, V | readonly V[]>): SmartAsyncIterator<V, R>
|
|
192
521
|
{
|
|
193
522
|
const iterator = this._iterator;
|
|
194
523
|
|
|
195
524
|
return new SmartAsyncIterator<V, R>(async function* ()
|
|
196
525
|
{
|
|
197
526
|
let index = 0;
|
|
198
|
-
|
|
199
527
|
while (true)
|
|
200
528
|
{
|
|
201
529
|
const result = await iterator.next();
|
|
202
530
|
if (result.done) { return result.value; }
|
|
203
531
|
|
|
204
532
|
const elements = await iteratee(result.value, index);
|
|
205
|
-
|
|
206
|
-
for await (const element of elements)
|
|
533
|
+
if (elements instanceof Array)
|
|
207
534
|
{
|
|
208
|
-
yield
|
|
535
|
+
for (const value of elements) { yield value; }
|
|
209
536
|
}
|
|
537
|
+
else { yield elements; }
|
|
210
538
|
|
|
211
539
|
index += 1;
|
|
212
540
|
}
|
|
213
541
|
});
|
|
214
542
|
}
|
|
215
543
|
|
|
544
|
+
/**
|
|
545
|
+
* Drops a given number of elements at the beginning of the iterator.
|
|
546
|
+
* The remaining elements will be included in a new iterator.
|
|
547
|
+
* See also {@link SmartAsyncIterator.take}.
|
|
548
|
+
*
|
|
549
|
+
* Since the iterator is lazy, the dropping process will
|
|
550
|
+
* be executed once the resulting iterator is materialized.
|
|
551
|
+
*
|
|
552
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
553
|
+
* This means that the original iterator won't be consumed until the
|
|
554
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
555
|
+
*
|
|
556
|
+
* Only the dropped elements will be consumed in the process.
|
|
557
|
+
* The rest of the iterator will be consumed only once the new one is.
|
|
558
|
+
*
|
|
559
|
+
* ```ts
|
|
560
|
+
* const iterator = new SmartAsyncIterator<number>([-2, -1, 0, 1, 2]);
|
|
561
|
+
* const result = iterator.drop(3);
|
|
562
|
+
*
|
|
563
|
+
* console.log(await result.toArray()); // [1, 2]
|
|
564
|
+
* ```
|
|
565
|
+
*
|
|
566
|
+
* @param count The number of elements to drop.
|
|
567
|
+
*
|
|
568
|
+
* @returns A new {@link SmartAsyncIterator} containing the remaining elements.
|
|
569
|
+
*/
|
|
216
570
|
public drop(count: number): SmartAsyncIterator<T, R | undefined>
|
|
217
571
|
{
|
|
218
572
|
const iterator = this._iterator;
|
|
@@ -220,7 +574,6 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
220
574
|
return new SmartAsyncIterator<T, R | undefined>(async function* ()
|
|
221
575
|
{
|
|
222
576
|
let index = 0;
|
|
223
|
-
|
|
224
577
|
while (index < count)
|
|
225
578
|
{
|
|
226
579
|
const result = await iterator.next();
|
|
@@ -238,6 +591,34 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
238
591
|
}
|
|
239
592
|
});
|
|
240
593
|
}
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* Takes a given number of elements at the beginning of the iterator.
|
|
597
|
+
* These elements will be included in a new iterator.
|
|
598
|
+
* See also {@link SmartAsyncIterator.drop}.
|
|
599
|
+
*
|
|
600
|
+
* Since the iterator is lazy, the taking process will
|
|
601
|
+
* be executed once the resulting iterator is materialized.
|
|
602
|
+
*
|
|
603
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
604
|
+
* This means that the original iterator won't be consumed until the
|
|
605
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
606
|
+
*
|
|
607
|
+
* Only the taken elements will be consumed from the original iterator.
|
|
608
|
+
* The rest of the original iterator will be available for further consumption.
|
|
609
|
+
*
|
|
610
|
+
* ```ts
|
|
611
|
+
* const iterator = new SmartAsyncIterator<number>([-2, -1, 0, 1, 2]);
|
|
612
|
+
* const result = iterator.take(3);
|
|
613
|
+
*
|
|
614
|
+
* console.log(await result.toArray()); // [-2, -1, 0]
|
|
615
|
+
* console.log(await iterator.toArray()); // [1, 2]
|
|
616
|
+
* ```
|
|
617
|
+
*
|
|
618
|
+
* @param limit The number of elements to take.
|
|
619
|
+
*
|
|
620
|
+
* @returns A new {@link SmartAsyncIterator} containing the taken elements.
|
|
621
|
+
*/
|
|
241
622
|
public take(limit: number): SmartAsyncIterator<T, R | undefined>
|
|
242
623
|
{
|
|
243
624
|
const iterator = this._iterator;
|
|
@@ -245,7 +626,6 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
245
626
|
return new SmartAsyncIterator<T, R | undefined>(async function* ()
|
|
246
627
|
{
|
|
247
628
|
let index = 0;
|
|
248
|
-
|
|
249
629
|
while (index < limit)
|
|
250
630
|
{
|
|
251
631
|
const result = await iterator.next();
|
|
@@ -260,6 +640,67 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
260
640
|
});
|
|
261
641
|
}
|
|
262
642
|
|
|
643
|
+
/**
|
|
644
|
+
* Finds the first element of the iterator that satisfies a given condition.
|
|
645
|
+
*
|
|
646
|
+
* This method will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
647
|
+
* The first element that satisfies the condition will be returned immediately.
|
|
648
|
+
*
|
|
649
|
+
* Only the elements that are necessary to find the first
|
|
650
|
+
* satisfying one will be consumed from the original iterator.
|
|
651
|
+
* The rest of the original iterator will be available for further consumption.
|
|
652
|
+
*
|
|
653
|
+
* Also note that:
|
|
654
|
+
* - If no element satisfies the condition, `undefined` will be returned once the entire iterator is consumed.
|
|
655
|
+
* - If the iterator is infinite and no element satisfies the condition, the method will never return.
|
|
656
|
+
*
|
|
657
|
+
* ```ts
|
|
658
|
+
* const iterator = new SmartAsyncIterator<number>([-2, -1, 0, 1, 2]);
|
|
659
|
+
* const result = await iterator.find(async (value) => value > 0);
|
|
660
|
+
*
|
|
661
|
+
* console.log(result); // 1
|
|
662
|
+
* ```
|
|
663
|
+
*
|
|
664
|
+
* @param predicate The condition to check for each element of the iterator.
|
|
665
|
+
*
|
|
666
|
+
* @returns
|
|
667
|
+
* A {@link Promise} that will resolve to the first element that satisfies the condition, `undefined` otherwise.
|
|
668
|
+
*/
|
|
669
|
+
public async find(predicate: MaybeAsyncIteratee<T, boolean>): Promise<T | undefined>;
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Finds the first element of the iterator that satisfies a given condition.
|
|
673
|
+
*
|
|
674
|
+
* This method will iterate over all elements of the iterator checking if they satisfy the condition.
|
|
675
|
+
* The first element that satisfies the condition will be returned immediately.
|
|
676
|
+
*
|
|
677
|
+
* Only the elements that are necessary to find the first
|
|
678
|
+
* satisfying one will be consumed from the original iterator.
|
|
679
|
+
* The rest of the original iterator will be available for further consumption.
|
|
680
|
+
*
|
|
681
|
+
* Also note that:
|
|
682
|
+
* - If no element satisfies the condition, `undefined` will be returned once the entire iterator is consumed.
|
|
683
|
+
* - If the iterator is infinite and no element satisfies the condition, the method will never return.
|
|
684
|
+
*
|
|
685
|
+
* ```ts
|
|
686
|
+
* const iterator = new SmartAsyncIterator<number | string>([-2, "-1", "0", 1, "2"]);
|
|
687
|
+
* const result = await iterator.find<number>(async (value) => typeof value === "number");
|
|
688
|
+
*
|
|
689
|
+
* console.log(result); // -2
|
|
690
|
+
* ```
|
|
691
|
+
*
|
|
692
|
+
* @template S
|
|
693
|
+
* The type of the element that satisfies the condition.
|
|
694
|
+
* This allows the type-system to infer the correct type of the result.
|
|
695
|
+
*
|
|
696
|
+
* It must be a subtype of the original type of the elements.
|
|
697
|
+
*
|
|
698
|
+
* @param predicate The type guard condition to check for each element of the iterator.
|
|
699
|
+
*
|
|
700
|
+
* @returns
|
|
701
|
+
* A {@link Promise} that will resolve to the first element that satisfies the condition, `undefined` otherwise.
|
|
702
|
+
*/
|
|
703
|
+
public async find<S extends T>(predicate: MaybeAsyncIteratee<T, boolean>): Promise<S | undefined>;
|
|
263
704
|
public async find(predicate: MaybeAsyncIteratee<T, boolean>): Promise<T | undefined>
|
|
264
705
|
{
|
|
265
706
|
let index = 0;
|
|
@@ -275,10 +716,54 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
275
716
|
}
|
|
276
717
|
}
|
|
277
718
|
|
|
719
|
+
/**
|
|
720
|
+
* Enumerates the elements of the iterator.
|
|
721
|
+
* Each element is be paired with its index in a new iterator.
|
|
722
|
+
*
|
|
723
|
+
* Since the iterator is lazy, the enumeration process will
|
|
724
|
+
* be executed once the resulting iterator is materialized.
|
|
725
|
+
*
|
|
726
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
727
|
+
* This means that the original iterator won't be consumed until the
|
|
728
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
729
|
+
*
|
|
730
|
+
* ```ts
|
|
731
|
+
* const iterator = new SmartAsyncIterator<string>(["A", "M", "N", "Z"]);
|
|
732
|
+
* const result = iterator.enumerate();
|
|
733
|
+
*
|
|
734
|
+
* for await (const [index, value] of result)
|
|
735
|
+
* {
|
|
736
|
+
* console.log(`${index}: ${value}`); // "0: A", "1: M", "2: N", "3: Z"
|
|
737
|
+
* }
|
|
738
|
+
* ```
|
|
739
|
+
*
|
|
740
|
+
* @returns A new {@link SmartAsyncIterator} containing the enumerated elements.
|
|
741
|
+
*/
|
|
278
742
|
public enumerate(): SmartAsyncIterator<[number, T], R>
|
|
279
743
|
{
|
|
280
744
|
return this.map((value, index) => [index, value]);
|
|
281
745
|
}
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Removes all duplicate elements from the iterator.
|
|
749
|
+
* The first occurrence of each element will be kept.
|
|
750
|
+
*
|
|
751
|
+
* Since the iterator is lazy, the deduplication process will
|
|
752
|
+
* be executed once the resulting iterator is materialized.
|
|
753
|
+
*
|
|
754
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
755
|
+
* This means that the original iterator won't be consumed until the
|
|
756
|
+
* new one is and that consuming one of them will consume the other as well.
|
|
757
|
+
*
|
|
758
|
+
* ```ts
|
|
759
|
+
* const iterator = new SmartAsyncIterator<number>([1, 1, 2, 3, 2, 3, 4, 5, 5, 4]);
|
|
760
|
+
* const result = iterator.unique();
|
|
761
|
+
*
|
|
762
|
+
* console.log(await result.toArray()); // [1, 2, 3, 4, 5]
|
|
763
|
+
* ```
|
|
764
|
+
*
|
|
765
|
+
* @returns A new {@link SmartAsyncIterator} containing only the unique elements.
|
|
766
|
+
*/
|
|
282
767
|
public unique(): SmartAsyncIterator<T, R>
|
|
283
768
|
{
|
|
284
769
|
const iterator = this._iterator;
|
|
@@ -286,11 +771,9 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
286
771
|
return new SmartAsyncIterator<T, R>(async function* ()
|
|
287
772
|
{
|
|
288
773
|
const values = new Set<T>();
|
|
289
|
-
|
|
290
774
|
while (true)
|
|
291
775
|
{
|
|
292
776
|
const result = await iterator.next();
|
|
293
|
-
|
|
294
777
|
if (result.done) { return result.value; }
|
|
295
778
|
if (values.has(result.value)) { continue; }
|
|
296
779
|
|
|
@@ -301,6 +784,21 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
301
784
|
});
|
|
302
785
|
}
|
|
303
786
|
|
|
787
|
+
/**
|
|
788
|
+
* Counts the number of elements in the iterator.
|
|
789
|
+
* This method will consume the entire iterator in the process.
|
|
790
|
+
*
|
|
791
|
+
* If the iterator is infinite, the method will never return.
|
|
792
|
+
*
|
|
793
|
+
* ```ts
|
|
794
|
+
* const iterator = new SmartAsyncIterator<number>([1, 2, 3, 4, 5]);
|
|
795
|
+
* const result = await iterator.count();
|
|
796
|
+
*
|
|
797
|
+
* console.log(result); // 5
|
|
798
|
+
* ```
|
|
799
|
+
*
|
|
800
|
+
* @returns A {@link Promise} that will resolve to the number of elements in the iterator.
|
|
801
|
+
*/
|
|
304
802
|
public async count(): Promise<number>
|
|
305
803
|
{
|
|
306
804
|
let index = 0;
|
|
@@ -313,6 +811,26 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
313
811
|
index += 1;
|
|
314
812
|
}
|
|
315
813
|
}
|
|
814
|
+
|
|
815
|
+
/**
|
|
816
|
+
* Iterates over all elements of the iterator.
|
|
817
|
+
* The elements are passed to the function along with their index.
|
|
818
|
+
*
|
|
819
|
+
* This method will consume the entire iterator in the process.
|
|
820
|
+
* If the iterator is infinite, the method will never return.
|
|
821
|
+
*
|
|
822
|
+
* ```ts
|
|
823
|
+
* const iterator = new SmartAsyncIterator<number>(["A", "M", "N", "Z"]);
|
|
824
|
+
* await iterator.forEach(async (value, index) =>
|
|
825
|
+
* {
|
|
826
|
+
* console.log(`${index}: ${value}`); // "0: A", "1: M", "2: N", "3: Z"
|
|
827
|
+
* }
|
|
828
|
+
* ```
|
|
829
|
+
*
|
|
830
|
+
* @param iteratee The function to apply to each element of the iterator.
|
|
831
|
+
*
|
|
832
|
+
* @returns A {@link Promise} that will resolve once the iteration is complete.
|
|
833
|
+
*/
|
|
316
834
|
public async forEach(iteratee: MaybeAsyncIteratee<T>): Promise<void>
|
|
317
835
|
{
|
|
318
836
|
let index = 0;
|
|
@@ -328,11 +846,140 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
328
846
|
}
|
|
329
847
|
}
|
|
330
848
|
|
|
849
|
+
/**
|
|
850
|
+
* Advances the iterator to the next element and returns the result.
|
|
851
|
+
* If the iterator requires it, a value must be provided to be passed to the next element.
|
|
852
|
+
*
|
|
853
|
+
* Once the iterator is done, the method will return an object with the `done` property set to `true`.
|
|
854
|
+
*
|
|
855
|
+
* ```ts
|
|
856
|
+
* const iterator = new SmartAsyncIterator<number>([1, 2, 3, 4, 5]);
|
|
857
|
+
*
|
|
858
|
+
* let result = await iterator.next();
|
|
859
|
+
* while (!result.done)
|
|
860
|
+
* {
|
|
861
|
+
* console.log(result.value); // 1, 2, 3, 4, 5
|
|
862
|
+
*
|
|
863
|
+
* result = await iterator.next();
|
|
864
|
+
* }
|
|
865
|
+
*
|
|
866
|
+
* console.log(result); // { done: true, value: undefined }
|
|
867
|
+
* ```
|
|
868
|
+
*
|
|
869
|
+
* @param values The value to pass to the next element, if required.
|
|
870
|
+
*
|
|
871
|
+
* @returns
|
|
872
|
+
* A {@link Promise} that will resolve to the result of the iteration, containing the value of the operation.
|
|
873
|
+
*/
|
|
331
874
|
public next(...values: N extends undefined ? [] : [N]): Promise<IteratorResult<T, R>>
|
|
332
875
|
{
|
|
333
876
|
return this._iterator.next(...values);
|
|
334
877
|
}
|
|
335
878
|
|
|
879
|
+
/**
|
|
880
|
+
* An utility method that may be used to close the iterator gracefully,
|
|
881
|
+
* free the resources and perform any cleanup operation.
|
|
882
|
+
* It may also be used to signal the end or to compute a specific final result of the iteration process.
|
|
883
|
+
*
|
|
884
|
+
* ```ts
|
|
885
|
+
* const iterator = new SmartAsyncIterator<number>({
|
|
886
|
+
* _index: 0,
|
|
887
|
+
* next: async function()
|
|
888
|
+
* {
|
|
889
|
+
* return { done: false, value: this._index += 1 };
|
|
890
|
+
* },
|
|
891
|
+
* return: async function() { console.log("Closing the iterator..."); }
|
|
892
|
+
* });
|
|
893
|
+
*
|
|
894
|
+
* for await (const value of iterator)
|
|
895
|
+
* {
|
|
896
|
+
* if (value > 5) { break; } // Closing the iterator...
|
|
897
|
+
*
|
|
898
|
+
* console.log(value); // 1, 2, 3, 4, 5
|
|
899
|
+
* }
|
|
900
|
+
* ```
|
|
901
|
+
*
|
|
902
|
+
* @param value The final value of the iterator.
|
|
903
|
+
*
|
|
904
|
+
* @returns A {@link Promise} that will resolve to the final result of the iterator.
|
|
905
|
+
*/
|
|
906
|
+
public async return(value?: MaybePromise<R>): Promise<IteratorResult<T, R>>
|
|
907
|
+
{
|
|
908
|
+
const _value = (await value) as R;
|
|
909
|
+
|
|
910
|
+
if (this._iterator.return) { return await this._iterator.return(_value); }
|
|
911
|
+
|
|
912
|
+
return { done: true, value: _value };
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* An utility method that may be used to close the iterator due to an error,
|
|
917
|
+
* free the resources and perform any cleanup operation.
|
|
918
|
+
* It may also be used to signal that an error occurred during the iteration process or to handle it.
|
|
919
|
+
*
|
|
920
|
+
* ```ts
|
|
921
|
+
* const iterator = new SmartAsyncIterator<number>({
|
|
922
|
+
* _index: 0,
|
|
923
|
+
* next: async function()
|
|
924
|
+
* {
|
|
925
|
+
* return { done: this._index > 10, value: this._index += 1 };
|
|
926
|
+
* },
|
|
927
|
+
* throw: async function(error)
|
|
928
|
+
* {
|
|
929
|
+
* console.warn(error.message);
|
|
930
|
+
*
|
|
931
|
+
* this._index = 0;
|
|
932
|
+
* }
|
|
933
|
+
* });
|
|
934
|
+
*
|
|
935
|
+
* for await (const value of iterator) // 1, 2, 3, 4, 5, "The index is too high.", 1, 2, 3, 4, 5, ...
|
|
936
|
+
* {
|
|
937
|
+
* try
|
|
938
|
+
* {
|
|
939
|
+
* if (value > 5) { throw new Error("The index is too high."); }
|
|
940
|
+
*
|
|
941
|
+
* console.log(value); // 1, 2, 3, 4, 5
|
|
942
|
+
* }
|
|
943
|
+
* catch (error) { await iterator.throw(error); }
|
|
944
|
+
* }
|
|
945
|
+
* ```
|
|
946
|
+
*
|
|
947
|
+
* @param error The error to throw into the iterator.
|
|
948
|
+
*
|
|
949
|
+
* @returns A {@link Promise} that will resolve to the final result of the iterator.
|
|
950
|
+
*/
|
|
951
|
+
public throw(error: unknown): Promise<IteratorResult<T, R>>
|
|
952
|
+
{
|
|
953
|
+
if (this._iterator.throw) { return this._iterator.throw(error); }
|
|
954
|
+
|
|
955
|
+
throw error;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
/**
|
|
959
|
+
* An utility method that aggregates the elements of the iterator using a given key function.
|
|
960
|
+
* The elements will be grouped by the resulting keys in a new specialized iterator.
|
|
961
|
+
* See {@link AggregatedAsyncIterator}.
|
|
962
|
+
*
|
|
963
|
+
* Since the iterator is lazy, the grouping process will
|
|
964
|
+
* be executed once the resulting iterator is materialized.
|
|
965
|
+
*
|
|
966
|
+
* A new iterator will be created, holding the reference to the original one.
|
|
967
|
+
* This means that the original iterator won't be consumed until the
|
|
968
|
+
* the new one is and that consuming one of them will consume the other as well.
|
|
969
|
+
*
|
|
970
|
+
* ```ts
|
|
971
|
+
* const iterator = new SmartAsyncIterator<number>([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
972
|
+
* const result = iterator.groupBy<string>(async (value) => value % 2 === 0 ? "even" : "odd");
|
|
973
|
+
*
|
|
974
|
+
* console.log(await result.toObject()); // { odd: [1, 3, 5, 7, 9], even: [2, 4, 6, 8, 10] }
|
|
975
|
+
* ```
|
|
976
|
+
*
|
|
977
|
+
* @template K The type of the keys used to group the elements.
|
|
978
|
+
*
|
|
979
|
+
* @param iteratee The key function to apply to each element of the iterator.
|
|
980
|
+
*
|
|
981
|
+
* @returns A new instance of the {@link AggregatedAsyncIterator} class containing the grouped elements.
|
|
982
|
+
*/
|
|
336
983
|
public groupBy<K extends PropertyKey>(iteratee: MaybeAsyncIteratee<T, K>): AggregatedAsyncIterator<K, T>
|
|
337
984
|
{
|
|
338
985
|
return new AggregatedAsyncIterator(this.map(async (element, index) =>
|
|
@@ -343,6 +990,24 @@ export default class SmartAsyncIterator<T, R = void, N = undefined> implements A
|
|
|
343
990
|
}));
|
|
344
991
|
}
|
|
345
992
|
|
|
993
|
+
/**
|
|
994
|
+
* Materializes the iterator into an array.
|
|
995
|
+
* This method will consume the entire iterator in the process.
|
|
996
|
+
*
|
|
997
|
+
* If the iterator is infinite, the method will never return.
|
|
998
|
+
*
|
|
999
|
+
* ```ts
|
|
1000
|
+
* const iterator = new SmartAsyncIterator(async function* ()
|
|
1001
|
+
* {
|
|
1002
|
+
* for (let i = 0; i < 5; i += 1) { yield i; }
|
|
1003
|
+
* });
|
|
1004
|
+
* const result = await iterator.toArray();
|
|
1005
|
+
*
|
|
1006
|
+
* console.log(result); // [0, 1, 2, 3, 4]
|
|
1007
|
+
* ```
|
|
1008
|
+
*
|
|
1009
|
+
* @returns A {@link Promise} that will resolve to an array containing all elements of the iterator.
|
|
1010
|
+
*/
|
|
346
1011
|
public toArray(): Promise<T[]>
|
|
347
1012
|
{
|
|
348
1013
|
return Array.fromAsync(this as AsyncIterable<T>);
|