Repository navigation
Expand file tree
/
Copy pathwhen.js
More file actions
71 lines (61 loc) · 1.66 KB
/
Copy pathwhen.js
File metadata and controls
71 lines (61 loc) · 1.66 KB
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
function when(condition, code, options = {}) {
assertFunction(condition, "condition");
assertFunction(code, "code");
const interval = getInterval(options);
let timer;
let generation = 0;
function checkCondition() {
const currentGeneration = generation;
const ready = condition();
const asynchronous = ready != null && typeof ready.then === "function";
if (asynchronous) Promise.resolve(ready).catch(() => {});
if (currentGeneration !== generation) return;
if (asynchronous) {
throw new TypeError("condition must return a synchronous value");
}
if (ready) {
clear();
code();
} else {
timer = setTimeout(checkCondition, interval);
}
}
function clear() {
generation++;
clearTimeout(timer);
}
function reset() {
clear();
checkCondition();
}
function setCondition(newCondition) {
assertFunction(newCondition, "condition");
condition = newCondition;
}
function setCode(newCode) {
assertFunction(newCode, "code");
code = newCode;
}
checkCondition();
return { clear, reset, setCondition, setCode };
}
function assertFunction(value, name) {
if (typeof value !== "function") {
throw new TypeError(`${name} must be a function`);
}
}
function getInterval(options) {
if (
options === null ||
typeof options !== "object" ||
Array.isArray(options)
) {
throw new TypeError("options must be an object");
}
const { interval = 10 } = options;
if (!Number.isInteger(interval) || interval < 1 || interval > 2147483647) {
throw new RangeError("interval must be an integer from 1 to 2147483647");
}
return interval;
}
module.exports = when;