@oscarpalmer/timer 0.42.0 → 0.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/constants.d.mts +4 -6
- package/dist/delay.d.mts +1 -2
- package/dist/get.d.mts +0 -1
- package/dist/global.d.mts +1 -2
- package/dist/index.d.mts +74 -97
- package/dist/index.mjs +172 -230
- package/dist/is.d.mts +1 -3
- package/dist/is.mjs +1 -1
- package/dist/models.d.mts +87 -5
- package/dist/repeat.d.mts +4 -3
- package/dist/repeat.mjs +3 -2
- package/dist/timer.d.mts +3 -50
- package/dist/timer.mjs +60 -91
- package/dist/wait.d.mts +4 -2
- package/dist/wait.mjs +3 -2
- package/dist/when.d.mts +3 -54
- package/dist/when.mjs +89 -126
- package/dist/work.d.mts +1 -3
- package/dist/work.mjs +1 -1
- package/package.json +11 -6
- package/src/constants.ts +4 -5
- package/src/delay.ts +0 -1
- package/src/get.ts +1 -1
- package/src/global.ts +1 -1
- package/src/index.ts +5 -5
- package/src/is.ts +2 -3
- package/src/models.ts +105 -4
- package/src/repeat.ts +4 -5
- package/src/timer.ts +75 -119
- package/src/wait.ts +4 -5
- package/src/when.ts +112 -158
- package/src/work.ts +3 -4
package/src/models.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type {Timer} from './timer';
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* Options for a repeating timer
|
|
5
3
|
*/
|
|
@@ -26,6 +24,60 @@ export type RepeatOptions = {
|
|
|
26
24
|
timeout: number;
|
|
27
25
|
};
|
|
28
26
|
|
|
27
|
+
export type Timer = {
|
|
28
|
+
/**
|
|
29
|
+
* Is the timer active?
|
|
30
|
+
*/
|
|
31
|
+
get active(): boolean;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Is the timer destroyed?
|
|
35
|
+
*/
|
|
36
|
+
get destroyed(): boolean;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Is the timer paused?
|
|
40
|
+
*/
|
|
41
|
+
get paused(): boolean;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Get the timer's origin _(if debugging is enabled)_
|
|
45
|
+
*/
|
|
46
|
+
get trace(): string | undefined;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Continue running the timer _(if it's paused)_
|
|
50
|
+
*/
|
|
51
|
+
continue(): Timer;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Destroy the timer
|
|
55
|
+
*/
|
|
56
|
+
destroy(): void;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Pause the timer _(if it's running)_
|
|
60
|
+
*/
|
|
61
|
+
pause(): Timer;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Restart the timer _(or start it, if it's not running)_
|
|
65
|
+
*/
|
|
66
|
+
restart(): Timer;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Start the timer _(if it's not running)_
|
|
70
|
+
*/
|
|
71
|
+
start(): Timer;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Stop the timer _(if it's running)_
|
|
75
|
+
*/
|
|
76
|
+
stop(): Timer;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export type TimerName = 'repeat' | 'wait' | 'when';
|
|
80
|
+
|
|
29
81
|
export type TimerOptions = {
|
|
30
82
|
onAfter: ((finished: boolean) => void) | undefined;
|
|
31
83
|
onError: (() => void) | undefined;
|
|
@@ -54,7 +106,55 @@ export class TimerTrace extends Error {
|
|
|
54
106
|
}
|
|
55
107
|
}
|
|
56
108
|
|
|
57
|
-
export type
|
|
109
|
+
export type When = {
|
|
110
|
+
/**
|
|
111
|
+
* Is the timer active?
|
|
112
|
+
*/
|
|
113
|
+
get active(): boolean;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Is the timer destroyed?
|
|
117
|
+
*/
|
|
118
|
+
get destroyed(): boolean;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Is the timer paused?
|
|
122
|
+
*/
|
|
123
|
+
get paused(): boolean;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Get the timer's origin _(if debugging is enabled)_
|
|
127
|
+
*/
|
|
128
|
+
get trace(): string | undefined;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Continues the timer _(if it was paused)_
|
|
132
|
+
*/
|
|
133
|
+
continue(): When;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Destroys the timer _(and stops it,if it was running)_
|
|
137
|
+
*/
|
|
138
|
+
destroy(): void;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Pauses the timer _(if it was running)_
|
|
142
|
+
*/
|
|
143
|
+
pause(): When;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Start the timer
|
|
147
|
+
*
|
|
148
|
+
* @param resolve Optional resolve callback
|
|
149
|
+
* @returns Promise that resolves when the condition is met
|
|
150
|
+
*/
|
|
151
|
+
start(resolve?: (() => void) | null): Promise<void>;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Stops the timer _(if it was running)_
|
|
155
|
+
*/
|
|
156
|
+
stop(): When;
|
|
157
|
+
};
|
|
58
158
|
|
|
59
159
|
/**
|
|
60
160
|
* Options for a conditional timer
|
|
@@ -78,6 +178,7 @@ export type WhenState = {
|
|
|
78
178
|
promise: Promise<void>;
|
|
79
179
|
rejecter?: () => void;
|
|
80
180
|
resolver?: () => void;
|
|
181
|
+
result: boolean;
|
|
81
182
|
started: boolean;
|
|
82
183
|
timer: Timer;
|
|
83
184
|
};
|
|
@@ -91,7 +192,7 @@ export type WorkHandler = (
|
|
|
91
192
|
|
|
92
193
|
export type WorkHandlerTimer = {
|
|
93
194
|
instance: Timer;
|
|
94
|
-
|
|
195
|
+
name: TimerName;
|
|
95
196
|
};
|
|
96
197
|
|
|
97
198
|
export type WorkHandlerType = 'continue' | 'pause' | 'restart' | 'start' | 'stop';
|
package/src/repeat.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import {TYPE_REPEAT} from './constants';
|
|
2
2
|
import {getCallback, getValidNumber} from './get';
|
|
3
3
|
import './global';
|
|
4
|
-
import {type RepeatOptions, TimerTrace} from './models';
|
|
5
|
-
import {
|
|
4
|
+
import {type RepeatOptions, type Timer, TimerTrace} from './models';
|
|
5
|
+
import {createTimer} from './timer';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Create a repeating timer
|
|
9
|
+
*
|
|
9
10
|
* @param callback Callback to run on each interval
|
|
10
11
|
* @param options Timer options
|
|
11
12
|
* @returns Timer instance
|
|
12
13
|
*/
|
|
13
14
|
export function repeat(callback: (index: number) => void, options?: Partial<RepeatOptions>): Timer {
|
|
14
|
-
return
|
|
15
|
+
return createTimer(
|
|
15
16
|
TYPE_REPEAT,
|
|
16
17
|
{
|
|
17
18
|
callback: getCallback(callback),
|
|
@@ -27,5 +28,3 @@ export function repeat(callback: (index: number) => void, options?: Partial<Repe
|
|
|
27
28
|
true,
|
|
28
29
|
);
|
|
29
30
|
}
|
|
30
|
-
|
|
31
|
-
export type {RepeatOptions, Timer};
|
package/src/timer.ts
CHANGED
|
@@ -1,135 +1,91 @@
|
|
|
1
1
|
import {noop} from '@oscarpalmer/atoms/function';
|
|
2
2
|
import {WORK_CONTINUE, WORK_PAUSE, WORK_RESTART, WORK_START, WORK_STOP} from './constants';
|
|
3
|
-
import type {TimerOptions, TimerState,
|
|
3
|
+
import type {Timer, TimerName, TimerOptions, TimerState, WorkHandlerType} from './models';
|
|
4
4
|
import {stop, work} from './work';
|
|
5
5
|
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return this.state.active;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Is the timer destroyed?
|
|
20
|
-
*/
|
|
21
|
-
get destroyed(): boolean {
|
|
22
|
-
return this.state.destroyed;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Is the timer paused?
|
|
27
|
-
*/
|
|
28
|
-
get paused(): boolean {
|
|
29
|
-
return this.state.paused;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Get the timer's origin _(if debugging is enabled)_
|
|
34
|
-
*/
|
|
35
|
-
get trace(): string | undefined {
|
|
36
|
-
return (globalThis._oscarpalmer_timer_debug ?? false) ? this.state.trace : undefined;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
constructor(
|
|
40
|
-
type: TimerType,
|
|
41
|
-
state: Pick<TimerState, 'callback' | 'trace'>,
|
|
42
|
-
protected readonly options: TimerOptions,
|
|
43
|
-
start: boolean,
|
|
44
|
-
) {
|
|
45
|
-
Object.defineProperty(this, '$timer', {
|
|
46
|
-
value: type,
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
this.state = {
|
|
50
|
-
...state,
|
|
51
|
-
active: false,
|
|
52
|
-
destroyed: false,
|
|
53
|
-
elapsed: 0,
|
|
54
|
-
frame: undefined,
|
|
55
|
-
index: 0,
|
|
56
|
-
paused: false,
|
|
57
|
-
total: 0,
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
if (start) {
|
|
61
|
-
this.start();
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Continue running the timer _(if it's paused)_
|
|
67
|
-
*/
|
|
68
|
-
continue(): Timer {
|
|
69
|
-
return this.#work(WORK_CONTINUE);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Destroy the timer
|
|
74
|
-
*/
|
|
75
|
-
destroy(): void {
|
|
76
|
-
this.state.destroyed = true;
|
|
77
|
-
|
|
78
|
-
this.options.onAfter = noop;
|
|
79
|
-
this.options.onError = noop;
|
|
80
|
-
this.state.callback = noop;
|
|
81
|
-
|
|
82
|
-
if (!globalThis._oscarpalmer_timer_debug) {
|
|
83
|
-
this.state.trace = undefined;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
stop(
|
|
6
|
+
export function createTimer(
|
|
7
|
+
name: TimerName,
|
|
8
|
+
pick: Pick<TimerState, 'callback' | 'trace'>,
|
|
9
|
+
options: TimerOptions,
|
|
10
|
+
start: boolean,
|
|
11
|
+
): Timer {
|
|
12
|
+
function worker(type: WorkHandlerType): Timer {
|
|
13
|
+
return work(
|
|
14
|
+
type,
|
|
87
15
|
{
|
|
88
|
-
|
|
89
|
-
|
|
16
|
+
name,
|
|
17
|
+
instance: instance as Timer,
|
|
90
18
|
},
|
|
91
|
-
|
|
92
|
-
|
|
19
|
+
state,
|
|
20
|
+
options,
|
|
93
21
|
);
|
|
94
22
|
}
|
|
95
23
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
24
|
+
const state: TimerState = {
|
|
25
|
+
...pick,
|
|
26
|
+
active: false,
|
|
27
|
+
destroyed: false,
|
|
28
|
+
elapsed: 0,
|
|
29
|
+
frame: undefined,
|
|
30
|
+
index: 0,
|
|
31
|
+
paused: false,
|
|
32
|
+
total: 0,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const instance = {
|
|
36
|
+
continue: () => worker(WORK_CONTINUE),
|
|
37
|
+
destroy: () => destroyTimer(name, instance as Timer, state, options),
|
|
38
|
+
pause: () => worker(WORK_PAUSE),
|
|
39
|
+
restart: () => worker(WORK_RESTART),
|
|
40
|
+
start: () => worker(WORK_START),
|
|
41
|
+
stop: () => worker(WORK_STOP),
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
Object.defineProperties(instance, {
|
|
45
|
+
$timer: {
|
|
46
|
+
enumerable: false,
|
|
47
|
+
value: name,
|
|
48
|
+
},
|
|
49
|
+
active: {
|
|
50
|
+
enumerable: true,
|
|
51
|
+
get: () => state.active,
|
|
52
|
+
},
|
|
53
|
+
destroyed: {
|
|
54
|
+
enumerable: true,
|
|
55
|
+
get: () => state.destroyed,
|
|
56
|
+
},
|
|
57
|
+
paused: {
|
|
58
|
+
enumerable: true,
|
|
59
|
+
get: () => state.paused,
|
|
60
|
+
},
|
|
61
|
+
trace: {
|
|
62
|
+
enumerable: true,
|
|
63
|
+
get: () => ((globalThis._oscarpalmer_timer_debug ?? false) ? state.trace : undefined),
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (start) {
|
|
68
|
+
instance.start();
|
|
101
69
|
}
|
|
102
70
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
*/
|
|
106
|
-
restart(): Timer {
|
|
107
|
-
return this.#work(WORK_RESTART);
|
|
108
|
-
}
|
|
71
|
+
return Object.freeze(instance) as Timer;
|
|
72
|
+
}
|
|
109
73
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
74
|
+
function destroyTimer(
|
|
75
|
+
name: TimerName,
|
|
76
|
+
instance: Timer,
|
|
77
|
+
state: TimerState,
|
|
78
|
+
options: TimerOptions,
|
|
79
|
+
): void {
|
|
80
|
+
state.destroyed = true;
|
|
116
81
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
stop(): Timer {
|
|
121
|
-
return this.#work(WORK_STOP);
|
|
122
|
-
}
|
|
82
|
+
options.onAfter = noop;
|
|
83
|
+
options.onError = noop;
|
|
84
|
+
state.callback = noop;
|
|
123
85
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
type,
|
|
127
|
-
{
|
|
128
|
-
instance: this,
|
|
129
|
-
type: this.$timer,
|
|
130
|
-
},
|
|
131
|
-
this.state,
|
|
132
|
-
this.options,
|
|
133
|
-
);
|
|
86
|
+
if (!globalThis._oscarpalmer_timer_debug) {
|
|
87
|
+
state.trace = undefined;
|
|
134
88
|
}
|
|
89
|
+
|
|
90
|
+
stop({instance, name}, state, options);
|
|
135
91
|
}
|
package/src/wait.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import {TYPE_WAIT} from './constants';
|
|
2
2
|
import {getCallback, getValidNumber} from './get';
|
|
3
3
|
import './global';
|
|
4
|
-
import {TimerTrace} from './models';
|
|
5
|
-
import {
|
|
4
|
+
import {type Timer, TimerTrace} from './models';
|
|
5
|
+
import {createTimer} from './timer';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Create a waiting timer
|
|
9
|
+
*
|
|
9
10
|
* @param callback Callback to run when the timer has finished
|
|
10
11
|
* @param time How long to wait for _(in milliseconds; defaults to screen refresh rate)_
|
|
11
12
|
*/
|
|
12
13
|
export function wait(callback: () => void, time?: number): Timer {
|
|
13
|
-
return
|
|
14
|
+
return createTimer(
|
|
14
15
|
TYPE_WAIT,
|
|
15
16
|
{
|
|
16
17
|
callback: getCallback(callback),
|
|
@@ -26,5 +27,3 @@ export function wait(callback: () => void, time?: number): Timer {
|
|
|
26
27
|
true,
|
|
27
28
|
);
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
-
export type {Timer};
|
package/src/when.ts
CHANGED
|
@@ -1,178 +1,73 @@
|
|
|
1
1
|
import {noop} from '@oscarpalmer/atoms/function';
|
|
2
|
-
import {MESSAGE_DESTROYED, MESSAGE_STARTED, TYPE_WHEN} from './constants';
|
|
2
|
+
import {MESSAGE_DESTROYED, MESSAGE_STARTED, TYPE_WHEN, WORK_CONTINUE} from './constants';
|
|
3
3
|
import {getValidNumber, getValidTimeout} from './get';
|
|
4
4
|
import './global';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
get active() {
|
|
23
|
-
return this.state.timer?.active ?? false;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Is the timer destroyed?
|
|
28
|
-
*/
|
|
29
|
-
get destroyed() {
|
|
30
|
-
return this.state.timer == null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Is the timer paused?
|
|
35
|
-
*/
|
|
36
|
-
get paused() {
|
|
37
|
-
return this.state.timer?.paused ?? false;
|
|
38
|
-
}
|
|
5
|
+
import {
|
|
6
|
+
TimerTrace,
|
|
7
|
+
type When,
|
|
8
|
+
type WhenOptions,
|
|
9
|
+
type WhenState,
|
|
10
|
+
type WorkHandlerType,
|
|
11
|
+
} from './models';
|
|
12
|
+
import {createTimer} from './timer';
|
|
13
|
+
|
|
14
|
+
function destroyWhen(state: WhenState): void {
|
|
15
|
+
state.timer?.destroy();
|
|
16
|
+
|
|
17
|
+
state.promise = undefined as never;
|
|
18
|
+
state.resolver = noop;
|
|
19
|
+
state.rejecter = noop;
|
|
20
|
+
state.timer = undefined as never;
|
|
21
|
+
}
|
|
39
22
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
23
|
+
function onAfter(instance: When, state: WhenState): void {
|
|
24
|
+
if (state.result) {
|
|
25
|
+
state.resolver?.();
|
|
26
|
+
} else {
|
|
27
|
+
state.rejecter?.();
|
|
45
28
|
}
|
|
46
29
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
value: TYPE_WHEN,
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
const {state} = this;
|
|
53
|
-
|
|
54
|
-
state.promise = new Promise<void>((resolve, reject) => {
|
|
55
|
-
state.resolver = resolve;
|
|
56
|
-
state.rejecter = reject;
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
let result = false;
|
|
60
|
-
|
|
61
|
-
this.state.timer = new Timer(
|
|
62
|
-
TYPE_WHEN,
|
|
63
|
-
{
|
|
64
|
-
callback(): void {
|
|
65
|
-
try {
|
|
66
|
-
if (condition()) {
|
|
67
|
-
result = true;
|
|
68
|
-
|
|
69
|
-
state.timer.stop();
|
|
70
|
-
}
|
|
71
|
-
} catch {
|
|
72
|
-
state.timer.stop();
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
trace: new TimerTrace().stack,
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
onAfter: () => {
|
|
79
|
-
if (result) {
|
|
80
|
-
state.resolver?.();
|
|
81
|
-
} else {
|
|
82
|
-
state.rejecter?.();
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
this.destroy();
|
|
86
|
-
},
|
|
87
|
-
onError: () => {
|
|
88
|
-
state.rejecter?.();
|
|
89
|
-
|
|
90
|
-
this.destroy();
|
|
91
|
-
},
|
|
92
|
-
count: getValidNumber(options?.count),
|
|
93
|
-
interval: getValidNumber(options?.interval),
|
|
94
|
-
timeout: getValidTimeout(options?.timeout),
|
|
95
|
-
},
|
|
96
|
-
false,
|
|
97
|
-
);
|
|
98
|
-
}
|
|
30
|
+
instance.destroy();
|
|
31
|
+
}
|
|
99
32
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
this.state.timer?.continue();
|
|
33
|
+
function onCallback(condition: () => boolean, state: WhenState): void {
|
|
34
|
+
try {
|
|
35
|
+
if (condition()) {
|
|
36
|
+
state.result = true;
|
|
105
37
|
|
|
106
|
-
|
|
38
|
+
state.timer.stop();
|
|
39
|
+
}
|
|
40
|
+
} catch {
|
|
41
|
+
state.timer.stop();
|
|
107
42
|
}
|
|
43
|
+
}
|
|
108
44
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
*/
|
|
112
|
-
destroy(): void {
|
|
113
|
-
const {state} = this;
|
|
45
|
+
function onError(instance: When, state: WhenState): void {
|
|
46
|
+
state.rejecter?.();
|
|
114
47
|
|
|
115
|
-
|
|
48
|
+
instance.destroy();
|
|
49
|
+
}
|
|
116
50
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
state.rejecter = noop;
|
|
120
|
-
state.timer = undefined as never;
|
|
121
|
-
}
|
|
51
|
+
function onWhen(type: WorkHandlerType, instance: When, state: WhenState): When {
|
|
52
|
+
state.timer?.[type]?.();
|
|
122
53
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
*/
|
|
126
|
-
pause(): When {
|
|
127
|
-
this.state.timer?.pause();
|
|
54
|
+
return instance;
|
|
55
|
+
}
|
|
128
56
|
|
|
129
|
-
|
|
57
|
+
function startWhen(state: WhenState, resolve?: (() => void) | null): Promise<void> {
|
|
58
|
+
if (state.timer == null) {
|
|
59
|
+
throw new Error(MESSAGE_DESTROYED);
|
|
130
60
|
}
|
|
131
61
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
* @param resolve Optional resolve callback
|
|
135
|
-
* @param reject Optional reject callback
|
|
136
|
-
* @returns Promise that resolves when the condition is met
|
|
137
|
-
*/
|
|
138
|
-
start(resolve?: (() => void) | null, reject?: (() => void) | null): Promise<void> {
|
|
139
|
-
const {state} = this;
|
|
140
|
-
|
|
141
|
-
if (state.timer == null) {
|
|
142
|
-
throw new Error(MESSAGE_DESTROYED);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
if (state.started) {
|
|
146
|
-
throw new Error(MESSAGE_STARTED);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
state.started = true;
|
|
150
|
-
|
|
151
|
-
state.timer.start();
|
|
152
|
-
|
|
153
|
-
return state.promise.then(resolve ?? noop, reject ?? noop);
|
|
62
|
+
if (state.started) {
|
|
63
|
+
throw new Error(MESSAGE_STARTED);
|
|
154
64
|
}
|
|
155
65
|
|
|
156
|
-
|
|
157
|
-
* Stops the timer _(if it was running)_
|
|
158
|
-
*/
|
|
159
|
-
stop(): When {
|
|
160
|
-
this.state.timer?.stop();
|
|
66
|
+
state.started = true;
|
|
161
67
|
|
|
162
|
-
|
|
163
|
-
}
|
|
68
|
+
state.timer.start();
|
|
164
69
|
|
|
165
|
-
|
|
166
|
-
* Start the timer
|
|
167
|
-
* @deprecated Use `start()` instead
|
|
168
|
-
* @param resolve Optional resolve callback
|
|
169
|
-
* @param reject Optional reject callback
|
|
170
|
-
* @returns Promise that resolves when the condition is met
|
|
171
|
-
*/
|
|
172
|
-
// oxlint-disable-next-line no-thenable: Returning a promise-like object, so it's ok ;)
|
|
173
|
-
then(resolve?: (() => void) | null, reject?: (() => void) | null): Promise<void> {
|
|
174
|
-
return this.start(resolve, reject);
|
|
175
|
-
}
|
|
70
|
+
return state.promise.then(resolve);
|
|
176
71
|
}
|
|
177
72
|
|
|
178
73
|
/**
|
|
@@ -182,7 +77,66 @@ class When {
|
|
|
182
77
|
* @returns Timer instance
|
|
183
78
|
*/
|
|
184
79
|
export function when(condition: () => boolean, options?: Partial<WhenOptions>): When {
|
|
185
|
-
|
|
186
|
-
|
|
80
|
+
const state: WhenState = {
|
|
81
|
+
promise: undefined as never,
|
|
82
|
+
result: false,
|
|
83
|
+
started: false,
|
|
84
|
+
timer: undefined as never,
|
|
85
|
+
};
|
|
187
86
|
|
|
188
|
-
|
|
87
|
+
let instance: When;
|
|
88
|
+
|
|
89
|
+
state.promise = new Promise<void>((resolve, reject) => {
|
|
90
|
+
state.resolver = resolve;
|
|
91
|
+
state.rejecter = reject;
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
state.timer = createTimer(
|
|
95
|
+
TYPE_WHEN,
|
|
96
|
+
{
|
|
97
|
+
callback: () => onCallback(condition, state),
|
|
98
|
+
trace: new TimerTrace().stack,
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
onAfter: () => onAfter(instance, state),
|
|
102
|
+
onError: () => onError(instance, state),
|
|
103
|
+
count: getValidNumber(options?.count),
|
|
104
|
+
interval: getValidNumber(options?.interval),
|
|
105
|
+
timeout: getValidTimeout(options?.timeout),
|
|
106
|
+
},
|
|
107
|
+
false,
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
instance = {
|
|
111
|
+
continue: () => onWhen(WORK_CONTINUE, instance, state),
|
|
112
|
+
destroy: () => destroyWhen(state),
|
|
113
|
+
pause: () => onWhen('pause', instance, state),
|
|
114
|
+
start: (resolve?: (() => void) | null) => startWhen(state, resolve),
|
|
115
|
+
stop: () => onWhen('stop', instance, state),
|
|
116
|
+
} as When;
|
|
117
|
+
|
|
118
|
+
Object.defineProperties(instance, {
|
|
119
|
+
$timer: {
|
|
120
|
+
enumerable: false,
|
|
121
|
+
value: TYPE_WHEN,
|
|
122
|
+
},
|
|
123
|
+
active: {
|
|
124
|
+
enumerable: true,
|
|
125
|
+
get: () => state.timer?.active ?? false,
|
|
126
|
+
},
|
|
127
|
+
destroyed: {
|
|
128
|
+
enumerable: true,
|
|
129
|
+
get: () => state.timer == null,
|
|
130
|
+
},
|
|
131
|
+
paused: {
|
|
132
|
+
enumerable: true,
|
|
133
|
+
get: () => state.timer?.paused ?? false,
|
|
134
|
+
},
|
|
135
|
+
trace: {
|
|
136
|
+
enumerable: true,
|
|
137
|
+
get: () => ((globalThis._oscarpalmer_timer_debug ?? false) ? state.timer?.trace : undefined),
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
return Object.freeze(instance) as When;
|
|
142
|
+
}
|