Skip to content

Commit 987cc9c

Browse files
committed
Commit
1 parent d716fa3 commit 987cc9c

File tree

2 files changed

+43
-16
lines changed

2 files changed

+43
-16
lines changed

json-parse-lazy-promise.ts

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,59 @@
22
import { ResolvablePromise } from 'https://ghuc.cc/worker-tools/resolvable-promise/index.ts';
33
import { pipe } from 'https://cdn.skypack.dev/[email protected]';
44

5-
const id = (_: any) => _;
5+
const id = <T = any>(_: T) => _;
66

77
type Awaitable<T> = T | PromiseLike<T>;
88

9-
// TODO: Make own module?
10-
// TODO: Add abort signal?
11-
export class JSONParseLazyPromise<T, TTask = T> implements Promise<T> {
9+
// FIXME: Ugh...
10+
class Task<T> {
1211
#task;
1312
#promise;
13+
#state = 'idle'
14+
15+
constructor(task: () => Awaitable<T>, promise = new ResolvablePromise<T>()) {
16+
this.#task = task;
17+
this.#promise = promise;
18+
}
19+
20+
execute() {
21+
if (this.#state === 'idle') {
22+
this.#state = 'pending'
23+
this.#promise.resolve(this.#task())
24+
this.#promise.then(() => { this.#state = 'fulfilled' }, () => { this.#state = 'rejected' })
25+
}
26+
}
27+
get state() { return this.#state }
28+
get promise() { return this.#promise }
29+
}
30+
31+
const lock = Symbol('key');
32+
33+
// TODO: Make own module?
34+
// TODO: Add abort signal?
35+
export class JSONParseLazyPromise<T, TT = T> implements Promise<T> {
36+
#task: Task<TT>;
1437
#mapFn;
1538
#mappedPromise;
1639

17-
constructor(
18-
task: () => Awaitable<TTask>,
19-
promise = new ResolvablePromise<TTask>(),
20-
mapFn?: ((value: TTask, i?: 0) => Awaitable<T>) | undefined | null,
40+
static from<T>(task: () => Awaitable<T>) {
41+
return new JSONParseLazyPromise<T>(lock, new Task(task))
42+
}
43+
44+
private constructor(
45+
key: symbol,
46+
task: Task<TT>,
47+
mapFn?: ((value: TT, i?: 0) => Awaitable<T>) | undefined | null,
2148
thisArg?: any,
2249
) {
50+
if (key !== lock) throw Error('Illegal constructor invocation');
2351
this.#task = task;
24-
this.#promise = promise;
2552
this.#mapFn = mapFn;
26-
this.#mappedPromise = promise.then(mapFn && (x => mapFn.call(thisArg, x, 0)))
53+
this.#mappedPromise = this.#task.promise.then(mapFn && (x => mapFn.call(thisArg, x, 0)))
2754
}
2855

29-
#execute() {
30-
this.#promise.resolve(this.#task());
56+
get state() {
57+
return this.#task.state;
3158
}
3259

3360
/**
@@ -38,7 +65,7 @@ export class JSONParseLazyPromise<T, TTask = T> implements Promise<T> {
3865
onfulfilled?: ((value: T) => Awaitable<U>) | undefined | null,
3966
onrejected?: ((reason: any) => Awaitable<V>) | undefined | null
4067
): Promise<U | V> {
41-
this.#execute();
68+
this.#task.execute();
4269
return this.#mappedPromise.then(onfulfilled, onrejected)
4370
}
4471

@@ -49,8 +76,8 @@ export class JSONParseLazyPromise<T, TTask = T> implements Promise<T> {
4976
map<U = T>(
5077
mapFn?: ((value: T, i?: 0) => Awaitable<U>) | undefined | null,
5178
thisArg?: any
52-
): JSONParseLazyPromise<U, TTask> {
53-
return new JSONParseLazyPromise(this.#task, this.#promise, pipe(this.#mapFn ?? id, mapFn ?? id), thisArg);
79+
): JSONParseLazyPromise<U, TT> {
80+
return new JSONParseLazyPromise(lock, this.#task, pipe(this.#mapFn??id, mapFn??id), thisArg);
5481
}
5582

5683
catch<V = never>(onrejected?: ((reason: any) => Awaitable<V>) | null): Promise<T | V> {

json-parse-stream.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export class JSONParseNexus<T = any> extends TransformStream<string | Uint8Array
7878

7979
promise<T = any>(jsonPath: string): JSONParseLazyPromise<T | undefined> {
8080
const stream = this.stream(jsonPath);
81-
return new JSONParseLazyPromise(async () => {
81+
return JSONParseLazyPromise.from(async () => {
8282
const x = await stream.getReader().read();
8383
return x.done ? undefined : x.value;
8484
})

0 commit comments

Comments
 (0)