-
Notifications
You must be signed in to change notification settings - Fork 28
/
Copy pathqueue.ts
65 lines (60 loc) · 1.57 KB
/
queue.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
import type { MakeProm, λ } from "./types.ts";
import noop from "./noop.ts";
/**
* Creates a `queue` function that accepts a function as it's only parameter.
* When `queue` is invoked, the passed in function is executed after the last
* function passed to `queue` has finished executing. The `queue` function
* returns the result of the passed in function asynchronously.
*
* Reading `queue.done` is `true` if no functions are currently executing /
* scheduled and otherwise a promise that resolves once the last function has
* stopped executing and no futher functions are queued.
*
* @example
* ```
* const queue = createQueue()
*
* queue(async () => {
* console.log('start a')
* await delay()
* return 'end a'
* }).then(console.log)
*
* queue(async () => {
* console.log('start b')
* await delay()
* return 'end b'
* }).then(console.log)
*
* queue(async () => {
* console.log('start c')
* await delay()
* return 'end c'
* }).then(console.log)
*
* await queue.done
*
* // start a
* // end a
* // start b
* // end b
* // start c
* // end c
* ```
*/
const createQueue = (): Queue => {
let last: Promise<unknown> | null = null;
const queued = (fun: λ) =>
last = (last ?? Promise.resolve()).catch(noop).then(fun).finally(
() => {
last = null;
},
);
return Object.defineProperty(queued, "done", {
get: () => last?.catch(noop).then(noop) ?? true,
}) as Queue;
};
export default createQueue;
type Queue = (<T extends λ<[], unknown>>(fun: T) => MakeProm<ReturnType<T>>) & {
done: Promise<void> | true;
};