forked from dotnet/runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpromise-controller.ts
More file actions
75 lines (67 loc) · 3.08 KB
/
Copy pathpromise-controller.ts
File metadata and controls
75 lines (67 loc) · 3.08 KB
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
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
import {
mono_assert
} from "./types";
/// a unique symbol used to mark a promise as controllable
export const promise_control_symbol = Symbol.for("wasm promise_control");
/// A PromiseController encapsulates a Promise together with easy access to its resolve and reject functions.
/// It's a bit like a TaskCompletionSource in .NET
export interface PromiseController<T = any> {
isDone: boolean;
readonly promise: Promise<T>;
resolve: (value: T | PromiseLike<T>) => void;
reject: (reason?: any) => void;
}
/// A Promise<T> with a controller attached
export interface ControllablePromise<T = any> extends Promise<T> {
[promise_control_symbol]: PromiseController<T>;
}
/// Just a pair of a promise and its controller
export interface PromiseAndController<T> {
promise: ControllablePromise<T>;
promise_control: PromiseController<T>;
}
/// Creates a new promise together with a controller that can be used to resolve or reject that promise.
/// Optionally takes callbacks to be called immediately after a promise is resolved or rejected.
export function createPromiseController<T>(afterResolve?: () => void, afterReject?: () => void): PromiseAndController<T> {
let promise_control: PromiseController<T> = null as unknown as PromiseController<T>;
const promise = new Promise<T>(function (resolve, reject) {
promise_control = {
isDone: false,
promise: null as unknown as Promise<T>,
resolve: (data: T | PromiseLike<T>) => {
if (!promise_control!.isDone) {
promise_control!.isDone = true;
resolve(data);
if (afterResolve) {
afterResolve();
}
}
},
reject: (reason: any) => {
if (!promise_control!.isDone) {
promise_control!.isDone = true;
reject(reason);
if (afterReject) {
afterReject();
}
}
}
};
});
(<any>promise_control).promise = promise;
const controllablePromise = promise as ControllablePromise<T>;
controllablePromise[promise_control_symbol] = promise_control;
return { promise: controllablePromise, promise_control: promise_control };
}
export function getPromiseController<T>(promise: ControllablePromise<T>): PromiseController<T>;
export function getPromiseController<T>(promise: Promise<T>): PromiseController<T> | undefined {
return (promise as ControllablePromise<T>)[promise_control_symbol];
}
export function isControllablePromise<T>(promise: Promise<T>): promise is ControllablePromise<T> {
return (promise as ControllablePromise<T>)[promise_control_symbol] !== undefined;
}
export function assertIsControllablePromise<T>(promise: Promise<T>): asserts promise is ControllablePromise<T> {
mono_assert(isControllablePromise(promise), "Promise is not controllable");
}