102 lines
2.4 KiB
TypeScript
102 lines
2.4 KiB
TypeScript
|
|
|
|
type RejectType = {
|
|
type: 'reject';
|
|
reason: string | Error;
|
|
};
|
|
|
|
type ResolveType<T> = {
|
|
type: 'resolve';
|
|
value?: T;
|
|
};
|
|
|
|
type Response<T> = ResolveType<T> | RejectType | {
|
|
type: 'timeout' | 'abort';
|
|
};
|
|
|
|
const enum TimeoutState {
|
|
notYetWait = 0,
|
|
waiting = 1,
|
|
done = 2,
|
|
timeout = 3,
|
|
}''
|
|
|
|
/**
|
|
* 재사용 가능한 Signal 클래스
|
|
*/
|
|
export class Signal<T = undefined> {
|
|
private resolved: boolean = false;
|
|
private timeoutState: TimeoutState = TimeoutState.notYetWait;
|
|
|
|
private _promise!: Promise<Response<T>>;
|
|
private _resolve!: (value: Response<T>) => void;
|
|
private timeoutID?: ReturnType<typeof setTimeout>;
|
|
|
|
constructor(public readonly timeoutMs?: number) {
|
|
this.reset();
|
|
}
|
|
|
|
public reset(): void {
|
|
if(this.timeoutID){
|
|
clearTimeout(this.timeoutID);
|
|
this.timeoutID = undefined;
|
|
}
|
|
|
|
this.resolved = false;
|
|
this.timeoutState = TimeoutState.notYetWait;
|
|
this._promise = new Promise((resolve) => {
|
|
this._resolve = resolve;
|
|
});
|
|
|
|
if(this.timeoutMs){
|
|
this.timeoutID = setTimeout(() => {
|
|
this._timeout();
|
|
}, this.timeoutMs);
|
|
}
|
|
}
|
|
|
|
private _timeout(){
|
|
if(this.timeoutState === TimeoutState.waiting){
|
|
this.resolved = true;
|
|
this._resolve({type: 'timeout'});
|
|
}
|
|
this.timeoutState = TimeoutState.timeout;
|
|
}
|
|
|
|
public async wait(): Promise<Response<T>>{
|
|
if(this.timeoutState === TimeoutState.timeout){
|
|
this.reset();
|
|
return {type: 'timeout'};
|
|
}
|
|
this.timeoutState = TimeoutState.waiting;
|
|
const result = await this._promise;
|
|
this.reset();
|
|
return result;
|
|
}
|
|
|
|
public abort(): void {
|
|
if(this.resolved){
|
|
return;
|
|
}
|
|
this.resolved = true;
|
|
this.timeoutState = TimeoutState.done;
|
|
if(this.timeoutID){
|
|
clearTimeout(this.timeoutID);
|
|
this.timeoutID = undefined;
|
|
}
|
|
this._resolve({type: 'abort'});
|
|
}
|
|
|
|
public notify(value?: T): void {
|
|
if(this.resolved){
|
|
return;
|
|
}
|
|
this.resolved = true;
|
|
this.timeoutState = TimeoutState.done;
|
|
if(this.timeoutID){
|
|
clearTimeout(this.timeoutID);
|
|
this.timeoutID = undefined;
|
|
}
|
|
this._resolve({type: 'resolve', value});
|
|
}
|
|
} |