79 lines
1.8 KiB
TypeScript
79 lines
1.8 KiB
TypeScript
enum ResolvableState {
|
|
WAITING,
|
|
PENDING,
|
|
ERROR,
|
|
DONE
|
|
}
|
|
|
|
class FetchOnce<T> {
|
|
protected data: T|undefined;
|
|
protected error: unknown|undefined;
|
|
protected state: ResolvableState = ResolvableState.WAITING;
|
|
protected pendings: [(res: Promise<T>|T) => void, (reason: unknown) => void][] = [];
|
|
|
|
constructor(protected fetchMethod?: () => Promise<T>) { }
|
|
|
|
public resolve(): Promise<T> {
|
|
return new Promise((resolve, reject) => {
|
|
switch (this.state) {
|
|
case ResolvableState.WAITING:
|
|
this.state = ResolvableState.PENDING;
|
|
this.pendings.push([resolve, reject]);
|
|
if (this.fetchMethod) this.parsePromise(this.fetchMethod());
|
|
break;
|
|
case ResolvableState.PENDING:
|
|
this.pendings.push([resolve, reject]);
|
|
break;
|
|
case ResolvableState.DONE:
|
|
resolve(this.data);
|
|
break;
|
|
case ResolvableState.ERROR:
|
|
reject(this.error);
|
|
break;
|
|
}
|
|
});
|
|
}
|
|
|
|
protected isFinished(): boolean {
|
|
return this.state === ResolvableState.DONE || this.state === ResolvableState.ERROR;
|
|
}
|
|
|
|
protected parsePromise(promise: Promise<T>): void {
|
|
promise.then((data) => {
|
|
this.data = data;
|
|
this.state = ResolvableState.DONE;
|
|
this.pendings.forEach(pending => pending[0](data));
|
|
}).catch(err => {
|
|
this.error = err;
|
|
this.state = ResolvableState.ERROR;
|
|
this.pendings.forEach(pending => pending[1](err));
|
|
});
|
|
}
|
|
}
|
|
|
|
export class Resolvable<T> extends FetchOnce<T> {
|
|
constructor(fetchMethod: () => Promise<T>) {
|
|
super(fetchMethod);
|
|
}
|
|
}
|
|
|
|
export class WaitForSync<T> extends FetchOnce<T> {
|
|
protected state: ResolvableState = ResolvableState.PENDING;
|
|
|
|
constructor() {
|
|
super(undefined);
|
|
}
|
|
|
|
public setData(data: T): void {
|
|
if (!this.isFinished()) {
|
|
this.parsePromise((async () => data)());
|
|
}
|
|
}
|
|
|
|
public setError(error: unknown): void {
|
|
if (!this.isFinished()) {
|
|
this.parsePromise((async () => { throw error; })());
|
|
}
|
|
}
|
|
}
|