/
mod.ts
78 lines (68 loc) · 2 KB
/
mod.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
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
import { MuxAsyncIterator } from "../async/mux_async_iterator.ts";
import { deferred } from "../async/deferred.ts";
export type Disposable = { dispose: () => void };
/**
* Generates an AsyncIterable which can be awaited on for one or more signals.
* `dispose()` can be called when you are finished waiting on the events.
*
* Example:
*
* ```ts
* import { signal } from "./mod.ts";
*
* const sig = signal("SIGUSR1", "SIGINT");
* setTimeout(() => {}, 5000); // Prevents exiting immediately
*
* for await (const _ of sig) {
* console.log("interrupt or usr1 signal received");
* }
*
* // At some other point in your code when finished listening:
* sig.dispose();
* ```
*
* @param signals - one or more signals to listen to
*/
export function signal(
...signals: [Deno.Signal, ...Deno.Signal[]]
): AsyncIterable<void> & Disposable {
const mux = new MuxAsyncIterator<void>();
if (signals.length < 1) {
throw new Error(
"No signals are given. You need to specify at least one signal to create a signal stream.",
);
}
const streams = signals.map(createSignalStream);
streams.forEach((stream) => {
mux.add(stream);
});
// Create dispose method for the muxer of signal streams.
const dispose = (): void => {
streams.forEach((stream) => {
stream.dispose();
});
};
return Object.assign(mux, { dispose });
}
function createSignalStream(
signal: Deno.Signal,
): AsyncIterable<void> & Disposable {
let streamContinues = deferred<boolean>();
const handler = () => {
streamContinues.resolve(true);
};
Deno.addSignalListener(signal, handler);
const gen = async function* () {
while (await streamContinues) {
streamContinues = deferred<boolean>();
yield undefined;
}
};
return Object.assign(gen(), {
dispose() {
streamContinues.resolve(false);
Deno.removeSignalListener(signal, handler);
},
});
}