This repository has been archived by the owner on Apr 10, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
/
sigaa-promise-stack.ts
131 lines (118 loc) · 3.36 KB
/
sigaa-promise-stack.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
type PromiseStackOrder = 'normal' | 'reverse';
/**
* @category Internal
*/
export interface FunctionPromise<T> {
(): Promise<T>;
}
/**
* Item in stack.
* @category Internal
*/
export interface PromiseItemStack<K, T> {
key: K;
promiseFunction?(): Promise<void>;
promise?: Promise<T>;
}
/**
* Abstraction to represent a class that performs chain functions and waits for each promise that the functions return.
* @category Internal
*/
export interface PromiseStack<K, T> {
/**
* Add promise in stack.
* The function is not called the moment it is added to the stack, but when it is your turn on the stack
* @param promiseFunction function to generate the promise
* @param key Key of promise array, to identify a function.
* @returns A promise that resolves with the function's response.
*/
addPromise(key: K, promiseFunction: FunctionPromise<T>): Promise<T>;
/**
* Get promises objects.
* Returns the functions that are still in the stack.
*/
readonly promises: PromiseItemStack<K, T>[];
/**
* flush the stack.
*/
flush(): void;
}
/**
* Class to control promise order
* Performs chain functions and waits for each promise that the functions return.
* @category Internal
*/
export class SigaaPromiseStack<K, T> implements PromiseStack<K, T> {
/**
* Order type.
* If it is reverse, the last entered will be the first executed. default is normal.
*/
private order: PromiseStackOrder;
/**
* Current promise running object as {key, promiseFunction, promise}.
*/
private promiseRunning?: PromiseItemStack<K, T>;
/**
* store all promises objects as {key, promiseFunction, promise}
*/
private storedPromises: PromiseItemStack<K, T>[] = [];
/**
* @param PromiseStackOrder [order] order of execution of the promises, if it is reverse, the last entered will be the first executed. default is normal.
*/
constructor(order?: PromiseStackOrder) {
this.order = order || 'normal';
}
/**
* @inheritdoc
*/
flush(): void {
this.storedPromises = [];
this.promiseRunning = undefined;
}
/**
* @inheritdoc
*/
get promises(): PromiseItemStack<K, T>[] {
if (this.promiseRunning) {
return [this.promiseRunning, ...this.storedPromises];
} else {
return this.storedPromises;
}
}
/**
* Loop to execute the entire promise stack
*/
private async promiseExecutor(): Promise<void> {
if (!this.promiseRunning) {
while (this.storedPromises.length > 0) {
if (this.order === 'normal') {
this.promiseRunning = this.storedPromises.shift();
} else if (this.order === 'reverse') {
this.promiseRunning = this.storedPromises.pop();
}
try {
if (this.promiseRunning?.promiseFunction) {
await this.promiseRunning.promiseFunction();
}
} finally {
this.promiseRunning = undefined;
}
}
}
}
/**
* @inheritdoc
*/
public addPromise(key: K, promiseFunction: FunctionPromise<T>): Promise<T> {
const promiseObject: PromiseItemStack<K, T> = { key };
const promise = new Promise<T>((resolve, reject) => {
promiseObject.promiseFunction = () => {
return promiseFunction().then(resolve, reject);
};
});
promiseObject.promise = promise;
this.storedPromises.push(promiseObject);
this.promiseExecutor();
return promise;
}
}