+1
-1
src/common/async/aborts.js
+1
-1
src/common/async/aborts.js
···
8
8
9
9
/**
10
10
* Create an abort signal tied to a timeout.
11
-
* Replaces `AbortSignal.timeout`, which doesn't consistently abort with a TimeoutError cross env.
11
+
* Replaces `AbortSignal.timeout`, which doesn't consistently abort with a `TimeoutError` cross env.
12
12
*
13
13
* @param {number} ms - timeout in milliseconds
14
14
* @returns {TimeoutSignal} the timeout signal
+28
src/common/async/sleep.js
+28
src/common/async/sleep.js
···
1
+
/** @module common/async */
2
+
3
+
/**
4
+
* @param {number} ms the number of ms to sleep
5
+
* @param {AbortSignal} [signal] an aptional abort signal, to cancel the sleep
6
+
* @returns {Promise<void>}
7
+
* a promise that resolves after given amount of time, and is interruptable with an abort signal.
8
+
*/
9
+
export function sleep(ms, signal) {
10
+
signal?.throwIfAborted()
11
+
12
+
const { resolve, reject, promise } = Promise.withResolvers()
13
+
const timeout = setTimeout(resolve, ms)
14
+
15
+
if (signal) {
16
+
const abortHandler = () => {
17
+
clearTimeout(timeout)
18
+
reject(signal.reason)
19
+
}
20
+
21
+
signal.addEventListener('abort', abortHandler)
22
+
promise.finally(() => {
23
+
signal.removeEventListener('abort', abortHandler)
24
+
})
25
+
}
26
+
27
+
return promise
28
+
}
+45
src/common/strict-map.js
+45
src/common/strict-map.js
···
1
+
/** @module common */
2
+
3
+
/**
4
+
* A map with methods to ensure key presence and safe update.
5
+
*
6
+
* @template K, V
7
+
* @augments {Map<K, V>}
8
+
*/
9
+
export class StrictMap extends Map {
10
+
11
+
/**
12
+
* @param {K} key to lookup in the map, throwing is missing
13
+
* @returns {V} the value from the map
14
+
* @throws {Error} if the key is not present in the map
15
+
*/
16
+
require(key) {
17
+
if (!this.has(key)) throw Error(`key is required but not in the map`)
18
+
19
+
const value = /** @type {V} */ (this.get(key))
20
+
return value
21
+
}
22
+
23
+
/**
24
+
* @param {K} key to lookup in the map
25
+
* @param {function(): V} maker a callback which will create the value in the map if not present.
26
+
* @returns {V} the value from the map, possibly newly created by {maker}
27
+
*/
28
+
ensure(key, maker) {
29
+
if (!this.has(key)) {
30
+
this.set(key, maker())
31
+
}
32
+
33
+
return /** @type {V} */ (this.get(key))
34
+
}
35
+
36
+
/**
37
+
* @param {K} key to update in the map
38
+
* @param {function(V=): V} update function which returns the new value for the map
39
+
*/
40
+
update(key, update) {
41
+
const current = this.get(key)
42
+
this.set(key, update(current))
43
+
}
44
+
45
+
}