-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathVirtualPromise.ts
88 lines (73 loc) · 3.04 KB
/
VirtualPromise.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import { PartialObserver } from 'rxjs/Observer';
import { Notification } from 'rxjs/Notification';
import { TestMessage } from 'rxjs/testing/TestMessage';
import { VirtualTestScheduler } from './VirtualTestScheduler';
import { next, complete } from './TestMessageValue';
export interface VirtualPromise extends Promise<any> {
messages: Array<TestMessage>;
}
export class BaseVirtualPromise implements VirtualPromise {
public readonly [Symbol.toStringTag]: 'Promise';
public readonly messages: Array<TestMessage>;
private observers: Array<PartialObserver<any>> = [];
constructor(private scheduler: VirtualTestScheduler, messages: Array<TestMessage>) {
this.messages = messages;
this.setup();
}
private setup(): void {
const subject = this;
const { messages } = subject;
messages.forEach((message: TestMessage) =>
subject.scheduler.scheduleAbsolute(
(x: Notification<any>) => {
subject.observers.slice(0);
subject.observers.forEach(x.observe.bind(x));
},
message.frame,
message.notification)
);
}
public then<TResult, TResult2 = never>(onfulfilled?: ((value: any) => TResult | PromiseLike<TResult>) | undefined | null,
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): VirtualPromise;
public then<TResult, TResult2 = never>(onfulfilled?: ((value: any) => TResult | PromiseLike<TResult>) | undefined | null,
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): VirtualPromise {
const subject = this;
const { scheduler, messages } = subject;
const updateObservers = (observer: PartialObserver<any>) => {
const idx = subject.observers.indexOf(observer);
subject.observers.splice(idx, 1);
};
let promise: Promise<TResult> | null = null;
const observer: PartialObserver<any> = {
next: (value: any) => {
if (!onfulfilled) {
return;
}
const ret = onfulfilled(value);
if (ret && typeof (ret as PromiseLike<TResult>).then === 'function') {
promise = ret as Promise<TResult>;
} else {
const frame = scheduler.now();
promise = new BaseVirtualPromise(scheduler, [next(frame, undefined), complete(frame)]);
}
updateObservers(observer);
},
error: (err: any) => {
if (!onrejected) {
return;
}
onrejected(err);
updateObservers(observer);
}
};
this.observers.push(observer);
return promise || new BaseVirtualPromise(scheduler, messages);
}
public catch(_onrejected?: (reason: any) => any | PromiseLike<any>): Promise<any>;
public catch(_onrejected?: (reason: any) => void): Promise<any> {
throw new Error('not implemented');
}
public finally(_onfinally?: (() => void) | undefined | null): Promise<any> {
throw new Error('not implemented');
}
}