generated from sapphiredev/sapphire-template
-
-
Notifications
You must be signed in to change notification settings - Fork 37
/
AsyncQueue.ts
67 lines (61 loc) · 1.65 KB
/
AsyncQueue.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
/**
* The AsyncQueue class used to sequentialize burst requests
*/
export class AsyncQueue {
/**
* The remaining amount of queued promises
*/
public get remaining(): number {
return this.promises.length;
}
/**
* The promises array
*/
private promises: InternalAsyncQueueDeferredPromise[] = [];
/**
* Waits for last promise and queues a new one
* @example
* const queue = new AsyncQueue();
* async function request(url, options) {
* await queue.wait();
* try {
* const result = await fetch(url, options);
* // Do some operations with 'result'
* } finally {
* // Remove first entry from the queue and resolve for the next entry
* queue.shift();
* }
* }
*
* request(someUrl1, someOptions1); // Will call fetch() immediately
* request(someUrl2, someOptions2); // Will call fetch() after the first finished
* request(someUrl3, someOptions3); // Will call fetch() after the second finished
*/
public wait(): Promise<void> {
const next = this.promises.length ? this.promises[this.promises.length - 1].promise : Promise.resolve();
// eslint-disable-next-line @typescript-eslint/init-declarations
let resolve: () => void;
const promise = new Promise<void>((res) => {
resolve = res;
});
this.promises.push({
resolve: resolve!,
promise
});
return next;
}
/**
* Frees the queue's lock for the next item to process
*/
public shift(): void {
const deferred = this.promises.shift();
if (typeof deferred !== 'undefined') deferred.resolve();
}
}
/**
* @internal
*/
interface InternalAsyncQueueDeferredPromise {
resolve(): void;
promise: Promise<void>;
}