@oscarpalmer/timer 0.38.1 → 0.39.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/dist/constants.js +2 -18
- package/dist/delay.js +3 -3
- package/dist/repeat.js +2 -2
- package/dist/timer.full.js +20 -175
- package/dist/timer.js +1 -1
- package/dist/wait.js +2 -2
- package/dist/when.js +3 -3
- package/dist/work.js +2 -2
- package/package.json +5 -5
- package/src/constants.ts +2 -43
- package/src/delay.ts +3 -3
- package/src/repeat.ts +2 -2
- package/src/timer.ts +3 -1
- package/src/wait.ts +2 -2
- package/src/when.ts +7 -3
- package/src/work.ts +2 -2
- package/types/constants.d.ts +2 -4
package/dist/constants.js
CHANGED
|
@@ -1,16 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
return new Promise((resolve) => {
|
|
3
|
-
const values = [];
|
|
4
|
-
let last;
|
|
5
|
-
function step(now) {
|
|
6
|
-
if (last != null) values.push(now - last);
|
|
7
|
-
last = now;
|
|
8
|
-
if (values.length >= 10) resolve(values.sort().slice(2, -2).reduce((first, second) => first + second, 0) / (values.length - 4));
|
|
9
|
-
else requestAnimationFrame(step);
|
|
10
|
-
}
|
|
11
|
-
requestAnimationFrame(step);
|
|
12
|
-
});
|
|
13
|
-
}
|
|
1
|
+
import FRAME_RATE_MS from "@oscarpalmer/atoms/frame-rate";
|
|
14
2
|
const BUFFER_INTERVAL = 5;
|
|
15
3
|
const DEFAULT_TIMEOUT = 3e4;
|
|
16
4
|
const MESSAGE_DESTROYED = "Timer has already been destroyed";
|
|
@@ -25,8 +13,4 @@ const WORK_PAUSE = "pause";
|
|
|
25
13
|
const WORK_RESTART = "restart";
|
|
26
14
|
const WORK_START = "start";
|
|
27
15
|
const WORK_STOP = "stop";
|
|
28
|
-
|
|
29
|
-
calculate().then((value) => {
|
|
30
|
-
MILLISECONDS = value;
|
|
31
|
-
});
|
|
32
|
-
export { BUFFER_INTERVAL, DEFAULT_TIMEOUT, MESSAGE_DESTROYED, MESSAGE_STARTED, MILLISECONDS, TIMERS_ACTIVE, TIMERS_HIDDEN, TYPE_REPEAT, TYPE_WAIT, TYPE_WHEN, WORK_CONTINUE, WORK_PAUSE, WORK_RESTART, WORK_START, WORK_STOP };
|
|
16
|
+
export { BUFFER_INTERVAL, DEFAULT_TIMEOUT, FRAME_RATE_MS, MESSAGE_DESTROYED, MESSAGE_STARTED, TIMERS_ACTIVE, TIMERS_HIDDEN, TYPE_REPEAT, TYPE_WAIT, TYPE_WHEN, WORK_CONTINUE, WORK_PAUSE, WORK_RESTART, WORK_START, WORK_STOP };
|
package/dist/delay.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { BUFFER_INTERVAL,
|
|
1
|
+
import { BUFFER_INTERVAL, FRAME_RATE_MS } from "./constants.js";
|
|
2
2
|
import { getValidNumber } from "./get.js";
|
|
3
3
|
function delay(time) {
|
|
4
4
|
return new Promise((resolve) => {
|
|
5
|
-
const interval = getValidNumber(time,
|
|
5
|
+
const interval = getValidNumber(time, FRAME_RATE_MS);
|
|
6
6
|
let start;
|
|
7
7
|
function step(now) {
|
|
8
8
|
start ??= now;
|
|
9
|
-
if (interval ===
|
|
9
|
+
if (interval === FRAME_RATE_MS || now - start >= interval - 5) resolve();
|
|
10
10
|
else requestAnimationFrame(step);
|
|
11
11
|
}
|
|
12
12
|
requestAnimationFrame(step);
|
package/dist/repeat.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FRAME_RATE_MS, TYPE_REPEAT } from "./constants.js";
|
|
2
2
|
import { getCallback, getValidNumber } from "./get.js";
|
|
3
3
|
import "./global.js";
|
|
4
4
|
import { TimerTrace } from "./models.js";
|
|
@@ -11,7 +11,7 @@ function repeat(callback, options) {
|
|
|
11
11
|
onAfter: getCallback(options?.onAfter),
|
|
12
12
|
onError: getCallback(options?.onTimeout),
|
|
13
13
|
count: getValidNumber(options?.count),
|
|
14
|
-
interval: getValidNumber(options?.interval,
|
|
14
|
+
interval: getValidNumber(options?.interval, FRAME_RATE_MS),
|
|
15
15
|
timeout: getValidNumber(options?.timeout)
|
|
16
16
|
}, true);
|
|
17
17
|
}
|
package/dist/timer.full.js
CHANGED
|
@@ -1,36 +1,29 @@
|
|
|
1
|
-
function calculate
|
|
1
|
+
function calculate() {
|
|
2
2
|
return new Promise((resolve) => {
|
|
3
3
|
const values = [];
|
|
4
4
|
let last;
|
|
5
5
|
function step(now) {
|
|
6
6
|
if (last != null) values.push(now - last);
|
|
7
7
|
last = now;
|
|
8
|
-
if (values.length >=
|
|
8
|
+
if (values.length >= CALCULATION_TOTAL) resolve(values.sort().slice(CALCULATION_TRIM_PART, -CALCULATION_TRIM_PART).reduce((first, second) => first + second, 0) / (values.length - CALCULATION_TRIM_TOTAL));
|
|
9
9
|
else requestAnimationFrame(step);
|
|
10
10
|
}
|
|
11
11
|
requestAnimationFrame(step);
|
|
12
12
|
});
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
var CALCULATION_TOTAL = 10;
|
|
15
|
+
var CALCULATION_TRIM_PART = 2;
|
|
16
|
+
var CALCULATION_TRIM_TOTAL = 4;
|
|
17
|
+
var FRAME_RATE_MS = 1e3 / 60;
|
|
18
|
+
calculate().then((value) => {
|
|
19
|
+
FRAME_RATE_MS = value;
|
|
20
|
+
});
|
|
21
|
+
var frame_rate_default = FRAME_RATE_MS;
|
|
17
22
|
const BUFFER_INTERVAL = 5;
|
|
18
23
|
const DEFAULT_TIMEOUT = 3e4;
|
|
19
|
-
/**
|
|
20
|
-
* Message to show when a when-timer is destroyed
|
|
21
|
-
*/
|
|
22
24
|
const MESSAGE_DESTROYED = "Timer has already been destroyed";
|
|
23
|
-
/**
|
|
24
|
-
* Message to show when a when-timer is started
|
|
25
|
-
*/
|
|
26
25
|
const MESSAGE_STARTED = "Timer has already been started";
|
|
27
|
-
/**
|
|
28
|
-
* A set of all active timers
|
|
29
|
-
*/
|
|
30
26
|
const TIMERS_ACTIVE = /* @__PURE__ */ new Set();
|
|
31
|
-
/**
|
|
32
|
-
* A set of timers that were paused due to the document being hidden
|
|
33
|
-
*/
|
|
34
27
|
const TIMERS_HIDDEN = /* @__PURE__ */ new Set();
|
|
35
28
|
const TYPE_REPEAT = "repeat";
|
|
36
29
|
const TYPE_WAIT = "wait";
|
|
@@ -40,14 +33,6 @@ const WORK_PAUSE = "pause";
|
|
|
40
33
|
const WORK_RESTART = "restart";
|
|
41
34
|
const WORK_START = "start";
|
|
42
35
|
const WORK_STOP = "stop";
|
|
43
|
-
/**
|
|
44
|
-
* A calculated average of the refresh rate of the display _(in milliseconds)_
|
|
45
|
-
*/
|
|
46
|
-
let MILLISECONDS = 1e3 / 60;
|
|
47
|
-
calculate$1().then((value) => {
|
|
48
|
-
MILLISECONDS = value;
|
|
49
|
-
});
|
|
50
|
-
|
|
51
36
|
if (globalThis._oscarpalmer_timers == null) Object.defineProperty(globalThis, "_oscarpalmer_timers", { get() {
|
|
52
37
|
return globalThis._oscarpalmer_timer_debug ? [...TIMERS_ACTIVE] : [];
|
|
53
38
|
} });
|
|
@@ -62,29 +47,8 @@ document.addEventListener("visibilitychange", () => {
|
|
|
62
47
|
}
|
|
63
48
|
from.clear();
|
|
64
49
|
});
|
|
65
|
-
|
|
66
|
-
function calculate() {
|
|
67
|
-
return new Promise((resolve) => {
|
|
68
|
-
const values = [];
|
|
69
|
-
let last;
|
|
70
|
-
function step(now) {
|
|
71
|
-
if (last != null) values.push(now - last);
|
|
72
|
-
last = now;
|
|
73
|
-
if (values.length >= CALCULATION_TOTAL) resolve(values.sort().slice(2, -2).reduce((first, second) => first + second, 0) / (values.length - CALCULATION_TRIM));
|
|
74
|
-
else requestAnimationFrame(step);
|
|
75
|
-
}
|
|
76
|
-
requestAnimationFrame(step);
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
50
|
function noop() {}
|
|
80
|
-
|
|
81
|
-
var CALCULATION_TRIM = 4;
|
|
82
|
-
let milliseconds = 1e3 / 60;
|
|
83
|
-
calculate().then((value) => {
|
|
84
|
-
milliseconds = value;
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
var TYPED_ARRAYS = new Set([
|
|
51
|
+
new Set([
|
|
88
52
|
Int8Array,
|
|
89
53
|
Uint8Array,
|
|
90
54
|
Uint8ClampedArray,
|
|
@@ -97,7 +61,6 @@ var TYPED_ARRAYS = new Set([
|
|
|
97
61
|
BigInt64Array,
|
|
98
62
|
BigUint64Array
|
|
99
63
|
]);
|
|
100
|
-
|
|
101
64
|
function getCallback(value) {
|
|
102
65
|
return typeof value === "function" ? value : noop;
|
|
103
66
|
}
|
|
@@ -108,68 +71,39 @@ function getValidNumber(value, defaultValue) {
|
|
|
108
71
|
const actualDefault = defaultValue ?? 0;
|
|
109
72
|
return typeof value === "number" && value > actualDefault ? value : actualDefault;
|
|
110
73
|
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Create a delayed promise that resolves after a certain amount of time
|
|
114
|
-
* @param time How long to wait for _(in milliseconds; defaults to screen refresh rate)_
|
|
115
|
-
* @returns A promise that resolves after the delay
|
|
116
|
-
*/
|
|
117
74
|
function delay(time) {
|
|
118
75
|
return new Promise((resolve) => {
|
|
119
|
-
const interval = getValidNumber(time,
|
|
76
|
+
const interval = getValidNumber(time, frame_rate_default);
|
|
120
77
|
let start;
|
|
121
78
|
function step(now) {
|
|
122
79
|
start ??= now;
|
|
123
|
-
if (interval ===
|
|
80
|
+
if (interval === frame_rate_default || now - start >= interval - BUFFER_INTERVAL) resolve();
|
|
124
81
|
else requestAnimationFrame(step);
|
|
125
82
|
}
|
|
126
83
|
requestAnimationFrame(step);
|
|
127
84
|
});
|
|
128
85
|
}
|
|
129
|
-
|
|
130
86
|
function is(names, value) {
|
|
131
87
|
return names.includes(value?.$timer);
|
|
132
88
|
}
|
|
133
|
-
/**
|
|
134
|
-
* Is the value a repeating timer?
|
|
135
|
-
* @param value Value to check
|
|
136
|
-
* @returns `true` if the value is a repeating timer
|
|
137
|
-
*/
|
|
138
89
|
function isRepeated(value) {
|
|
139
90
|
return is([TYPE_REPEAT], value);
|
|
140
91
|
}
|
|
141
|
-
/**
|
|
142
|
-
* Is the value a timer?
|
|
143
|
-
* @param value Value to check
|
|
144
|
-
* @returns `true` if the value is a timer
|
|
145
|
-
*/
|
|
146
92
|
function isTimer(value) {
|
|
147
93
|
return is([TYPE_REPEAT, TYPE_WAIT], value);
|
|
148
94
|
}
|
|
149
|
-
/**
|
|
150
|
-
* Is the value a waiting timer?
|
|
151
|
-
* @param value Value to check
|
|
152
|
-
* @returns `true` if the value is a waiting timer
|
|
153
|
-
*/
|
|
154
95
|
function isWaited(value) {
|
|
155
96
|
return is([TYPE_WAIT], value);
|
|
156
97
|
}
|
|
157
|
-
/**
|
|
158
|
-
* Is the value a conditional timer?
|
|
159
|
-
* @param value Value to check
|
|
160
|
-
* @returns `true` if the value is a conditional timer
|
|
161
|
-
*/
|
|
162
98
|
function isWhen(value) {
|
|
163
99
|
return is([TYPE_WHEN], value) && typeof value.then === "function";
|
|
164
100
|
}
|
|
165
|
-
|
|
166
101
|
var TimerTrace = class extends Error {
|
|
167
102
|
constructor() {
|
|
168
103
|
super();
|
|
169
104
|
this.name = "TimerTrace";
|
|
170
105
|
}
|
|
171
106
|
};
|
|
172
|
-
|
|
173
107
|
function finish(timer, state, options, success) {
|
|
174
108
|
cancelAnimationFrame(state.frame);
|
|
175
109
|
TIMERS_ACTIVE.delete(timer.instance);
|
|
@@ -205,7 +139,7 @@ function run(timer, state, options) {
|
|
|
205
139
|
finish(timer, state, options, false);
|
|
206
140
|
return;
|
|
207
141
|
}
|
|
208
|
-
if (options.interval ===
|
|
142
|
+
if (options.interval === frame_rate_default || state.elapsed >= options.interval - BUFFER_INTERVAL) {
|
|
209
143
|
if (options.count > -1) state.callback(state.index);
|
|
210
144
|
start = now;
|
|
211
145
|
state.elapsed = 0;
|
|
@@ -249,36 +183,23 @@ function work(type, timer, state, options) {
|
|
|
249
183
|
state.frame = requestAnimationFrame(runner);
|
|
250
184
|
return timer.instance;
|
|
251
185
|
}
|
|
252
|
-
|
|
253
186
|
var Timer = class {
|
|
254
187
|
state;
|
|
255
|
-
/**
|
|
256
|
-
* Is the timer active?
|
|
257
|
-
*/
|
|
258
188
|
get active() {
|
|
259
189
|
return this.state.active;
|
|
260
190
|
}
|
|
261
|
-
/**
|
|
262
|
-
* Is the timer destroyed?
|
|
263
|
-
*/
|
|
264
191
|
get destroyed() {
|
|
265
192
|
return this.state.destroyed;
|
|
266
193
|
}
|
|
267
|
-
/**
|
|
268
|
-
* Is the timer paused?
|
|
269
|
-
*/
|
|
270
194
|
get paused() {
|
|
271
195
|
return this.state.paused;
|
|
272
196
|
}
|
|
273
|
-
/**
|
|
274
|
-
* Get the timer's origin _(if debugging is enabled)_
|
|
275
|
-
*/
|
|
276
197
|
get trace() {
|
|
277
198
|
return globalThis._oscarpalmer_timer_debug ?? false ? this.state.trace : void 0;
|
|
278
199
|
}
|
|
279
200
|
constructor(type, state, options, start) {
|
|
280
201
|
this.options = options;
|
|
281
|
-
this
|
|
202
|
+
Object.defineProperty(this, "$timer", { value: type });
|
|
282
203
|
this.state = {
|
|
283
204
|
...state,
|
|
284
205
|
active: false,
|
|
@@ -291,15 +212,9 @@ var Timer = class {
|
|
|
291
212
|
};
|
|
292
213
|
if (start) this.start();
|
|
293
214
|
}
|
|
294
|
-
/**
|
|
295
|
-
* Continue running the timer _(if it's paused)_
|
|
296
|
-
*/
|
|
297
215
|
continue() {
|
|
298
216
|
return this.#work(WORK_CONTINUE);
|
|
299
217
|
}
|
|
300
|
-
/**
|
|
301
|
-
* Destroy the timer
|
|
302
|
-
*/
|
|
303
218
|
destroy() {
|
|
304
219
|
this.state.destroyed = true;
|
|
305
220
|
this.options.onAfter = noop;
|
|
@@ -311,27 +226,15 @@ var Timer = class {
|
|
|
311
226
|
type: this.$timer
|
|
312
227
|
}, this.state, this.options);
|
|
313
228
|
}
|
|
314
|
-
/**
|
|
315
|
-
* Pause the timer _(if it's running)_
|
|
316
|
-
*/
|
|
317
229
|
pause() {
|
|
318
230
|
return this.#work(WORK_PAUSE);
|
|
319
231
|
}
|
|
320
|
-
/**
|
|
321
|
-
* Restart the timer _(or start it, if it's not running)_
|
|
322
|
-
*/
|
|
323
232
|
restart() {
|
|
324
233
|
return this.#work(WORK_RESTART);
|
|
325
234
|
}
|
|
326
|
-
/**
|
|
327
|
-
* Start the timer _(if it's not running)_
|
|
328
|
-
*/
|
|
329
235
|
start() {
|
|
330
236
|
return this.#work(WORK_START);
|
|
331
237
|
}
|
|
332
|
-
/**
|
|
333
|
-
* Stop the timer _(if it's running)_
|
|
334
|
-
*/
|
|
335
238
|
stop() {
|
|
336
239
|
return this.#work(WORK_STOP);
|
|
337
240
|
}
|
|
@@ -342,13 +245,6 @@ var Timer = class {
|
|
|
342
245
|
}, this.state, this.options);
|
|
343
246
|
}
|
|
344
247
|
};
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
* Create a repeating timer
|
|
348
|
-
* @param callback Callback to run on each interval
|
|
349
|
-
* @param options Timer options
|
|
350
|
-
* @returns Timer instance
|
|
351
|
-
*/
|
|
352
248
|
function repeat(callback, options) {
|
|
353
249
|
return new Timer(TYPE_REPEAT, {
|
|
354
250
|
callback: getCallback(callback),
|
|
@@ -357,16 +253,10 @@ function repeat(callback, options) {
|
|
|
357
253
|
onAfter: getCallback(options?.onAfter),
|
|
358
254
|
onError: getCallback(options?.onTimeout),
|
|
359
255
|
count: getValidNumber(options?.count),
|
|
360
|
-
interval: getValidNumber(options?.interval,
|
|
256
|
+
interval: getValidNumber(options?.interval, frame_rate_default),
|
|
361
257
|
timeout: getValidNumber(options?.timeout)
|
|
362
258
|
}, true);
|
|
363
259
|
}
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* Create a waiting timer
|
|
367
|
-
* @param callback Callback to run when the timer has finished
|
|
368
|
-
* @param time How long to wait for _(in milliseconds; defaults to screen refresh rate)_
|
|
369
|
-
*/
|
|
370
260
|
function wait(callback, time) {
|
|
371
261
|
return new Timer(TYPE_WAIT, {
|
|
372
262
|
callback: getCallback(callback),
|
|
@@ -375,13 +265,11 @@ function wait(callback, time) {
|
|
|
375
265
|
onAfter: void 0,
|
|
376
266
|
onError: void 0,
|
|
377
267
|
count: -1,
|
|
378
|
-
interval: getValidNumber(time,
|
|
268
|
+
interval: getValidNumber(time, frame_rate_default),
|
|
379
269
|
timeout: 0
|
|
380
270
|
}, true);
|
|
381
271
|
}
|
|
382
|
-
|
|
383
272
|
var When = class {
|
|
384
|
-
$timer = TYPE_WHEN;
|
|
385
273
|
state = {
|
|
386
274
|
promise: void 0,
|
|
387
275
|
rejecter: void 0,
|
|
@@ -389,31 +277,20 @@ var When = class {
|
|
|
389
277
|
started: false,
|
|
390
278
|
timer: void 0
|
|
391
279
|
};
|
|
392
|
-
/**
|
|
393
|
-
* Is the timer active?
|
|
394
|
-
*/
|
|
395
280
|
get active() {
|
|
396
281
|
return this.state.timer?.active ?? false;
|
|
397
282
|
}
|
|
398
|
-
/**
|
|
399
|
-
* Is the timer destroyed?
|
|
400
|
-
*/
|
|
401
283
|
get destroyed() {
|
|
402
284
|
return this.state.timer == null;
|
|
403
285
|
}
|
|
404
|
-
/**
|
|
405
|
-
* Is the timer paused?
|
|
406
|
-
*/
|
|
407
286
|
get paused() {
|
|
408
287
|
return this.state.timer?.paused ?? false;
|
|
409
288
|
}
|
|
410
|
-
/**
|
|
411
|
-
* Get the timer's origin _(if debugging is enabled)_
|
|
412
|
-
*/
|
|
413
289
|
get trace() {
|
|
414
290
|
return globalThis._oscarpalmer_timer_debug ?? false ? this.state.timer?.trace : void 0;
|
|
415
291
|
}
|
|
416
292
|
constructor(condition, options) {
|
|
293
|
+
Object.defineProperty(this, "$timer", { value: TYPE_WHEN });
|
|
417
294
|
const { state } = this;
|
|
418
295
|
state.promise = new Promise((resolve, reject) => {
|
|
419
296
|
state.resolver = resolve;
|
|
@@ -443,20 +320,14 @@ var When = class {
|
|
|
443
320
|
this.destroy();
|
|
444
321
|
},
|
|
445
322
|
count: getValidNumber(options?.count),
|
|
446
|
-
interval: getValidNumber(options?.interval,
|
|
323
|
+
interval: getValidNumber(options?.interval, frame_rate_default),
|
|
447
324
|
timeout: getValidTimeout(options?.timeout)
|
|
448
325
|
}, false);
|
|
449
326
|
}
|
|
450
|
-
/**
|
|
451
|
-
* Continues the timer _(if it was paused)_
|
|
452
|
-
*/
|
|
453
327
|
continue() {
|
|
454
328
|
this.state.timer?.continue();
|
|
455
329
|
return this;
|
|
456
330
|
}
|
|
457
|
-
/**
|
|
458
|
-
* Destroys the timer _(and stops it,if it was running)_
|
|
459
|
-
*/
|
|
460
331
|
destroy() {
|
|
461
332
|
const { state } = this;
|
|
462
333
|
state.timer?.destroy();
|
|
@@ -465,19 +336,10 @@ var When = class {
|
|
|
465
336
|
state.rejecter = noop;
|
|
466
337
|
state.timer = void 0;
|
|
467
338
|
}
|
|
468
|
-
/**
|
|
469
|
-
* Pauses the timer _(if it was running)_
|
|
470
|
-
*/
|
|
471
339
|
pause() {
|
|
472
340
|
this.state.timer?.pause();
|
|
473
341
|
return this;
|
|
474
342
|
}
|
|
475
|
-
/**
|
|
476
|
-
* Start the timer
|
|
477
|
-
* @param resolve Optional resolve callback
|
|
478
|
-
* @param reject Optional reject callback
|
|
479
|
-
* @returns Promise that resolves when the condition is met
|
|
480
|
-
*/
|
|
481
343
|
start(resolve, reject) {
|
|
482
344
|
const { state } = this;
|
|
483
345
|
if (state.timer == null) throw new Error(MESSAGE_DESTROYED);
|
|
@@ -486,32 +348,15 @@ var When = class {
|
|
|
486
348
|
state.timer.start();
|
|
487
349
|
return state.promise.then(resolve ?? noop, reject ?? noop);
|
|
488
350
|
}
|
|
489
|
-
/**
|
|
490
|
-
* Stops the timer _(if it was running)_
|
|
491
|
-
*/
|
|
492
351
|
stop() {
|
|
493
352
|
this.state.timer?.stop();
|
|
494
353
|
return this;
|
|
495
354
|
}
|
|
496
|
-
/**
|
|
497
|
-
* Start the timer
|
|
498
|
-
* @deprecated Use `start()` instead
|
|
499
|
-
* @param resolve Optional resolve callback
|
|
500
|
-
* @param reject Optional reject callback
|
|
501
|
-
* @returns Promise that resolves when the condition is met
|
|
502
|
-
*/
|
|
503
355
|
then(resolve, reject) {
|
|
504
356
|
return this.start(resolve, reject);
|
|
505
357
|
}
|
|
506
358
|
};
|
|
507
|
-
/**
|
|
508
|
-
* Create a conditional timer
|
|
509
|
-
* @param condition Condition to check
|
|
510
|
-
* @param options Timer options
|
|
511
|
-
* @returns Timer instance
|
|
512
|
-
*/
|
|
513
359
|
function when(condition, options) {
|
|
514
360
|
return new When(condition, options);
|
|
515
361
|
}
|
|
516
|
-
|
|
517
|
-
export { delay, isRepeated, isTimer, isWaited, isWhen, repeat, wait, when };
|
|
362
|
+
export { delay, isRepeated, isTimer, isWaited, isWhen, repeat, wait, when };
|
package/dist/timer.js
CHANGED
package/dist/wait.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FRAME_RATE_MS, TYPE_WAIT } from "./constants.js";
|
|
2
2
|
import { getCallback, getValidNumber } from "./get.js";
|
|
3
3
|
import "./global.js";
|
|
4
4
|
import { TimerTrace } from "./models.js";
|
|
@@ -11,7 +11,7 @@ function wait(callback, time) {
|
|
|
11
11
|
onAfter: void 0,
|
|
12
12
|
onError: void 0,
|
|
13
13
|
count: -1,
|
|
14
|
-
interval: getValidNumber(time,
|
|
14
|
+
interval: getValidNumber(time, FRAME_RATE_MS),
|
|
15
15
|
timeout: 0
|
|
16
16
|
}, true);
|
|
17
17
|
}
|
package/dist/when.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { MESSAGE_DESTROYED, MESSAGE_STARTED,
|
|
1
|
+
import { FRAME_RATE_MS, MESSAGE_DESTROYED, MESSAGE_STARTED, TYPE_WHEN } from "./constants.js";
|
|
2
2
|
import { getValidNumber, getValidTimeout } from "./get.js";
|
|
3
3
|
import "./global.js";
|
|
4
4
|
import { TimerTrace } from "./models.js";
|
|
5
5
|
import { Timer } from "./timer.js";
|
|
6
6
|
import { noop } from "@oscarpalmer/atoms/function";
|
|
7
7
|
var When = class {
|
|
8
|
-
$timer = TYPE_WHEN;
|
|
9
8
|
state = {
|
|
10
9
|
promise: void 0,
|
|
11
10
|
rejecter: void 0,
|
|
@@ -26,6 +25,7 @@ var When = class {
|
|
|
26
25
|
return globalThis._oscarpalmer_timer_debug ?? false ? this.state.timer?.trace : void 0;
|
|
27
26
|
}
|
|
28
27
|
constructor(condition, options) {
|
|
28
|
+
Object.defineProperty(this, "$timer", { value: TYPE_WHEN });
|
|
29
29
|
const { state } = this;
|
|
30
30
|
state.promise = new Promise((resolve, reject) => {
|
|
31
31
|
state.resolver = resolve;
|
|
@@ -55,7 +55,7 @@ var When = class {
|
|
|
55
55
|
this.destroy();
|
|
56
56
|
},
|
|
57
57
|
count: getValidNumber(options?.count),
|
|
58
|
-
interval: getValidNumber(options?.interval,
|
|
58
|
+
interval: getValidNumber(options?.interval, FRAME_RATE_MS),
|
|
59
59
|
timeout: getValidTimeout(options?.timeout)
|
|
60
60
|
}, false);
|
|
61
61
|
}
|
package/dist/work.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BUFFER_INTERVAL,
|
|
1
|
+
import { BUFFER_INTERVAL, FRAME_RATE_MS, TIMERS_ACTIVE, TYPE_WAIT, WORK_CONTINUE, WORK_PAUSE, WORK_RESTART, WORK_START, WORK_STOP } from "./constants.js";
|
|
2
2
|
function finish(timer, state, options, success) {
|
|
3
3
|
cancelAnimationFrame(state.frame);
|
|
4
4
|
TIMERS_ACTIVE.delete(timer.instance);
|
|
@@ -34,7 +34,7 @@ function run(timer, state, options) {
|
|
|
34
34
|
finish(timer, state, options, false);
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
|
-
if (options.interval ===
|
|
37
|
+
if (options.interval === FRAME_RATE_MS || state.elapsed >= options.interval - 5) {
|
|
38
38
|
if (options.count > -1) state.callback(state.index);
|
|
39
39
|
start = now;
|
|
40
40
|
state.elapsed = 0;
|
package/package.json
CHANGED
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
"url": "https://oscarpalmer.se"
|
|
5
5
|
},
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@oscarpalmer/atoms": "^0.
|
|
7
|
+
"@oscarpalmer/atoms": "^0.117"
|
|
8
8
|
},
|
|
9
9
|
"description": "A better solution for timeout- and interval-based timers.",
|
|
10
10
|
"devDependencies": {
|
|
11
11
|
"@types/node": "^25",
|
|
12
12
|
"@vitest/coverage-istanbul": "^4",
|
|
13
13
|
"jsdom": "^27.3",
|
|
14
|
-
"oxfmt": "^0.
|
|
15
|
-
"oxlint": "^1.
|
|
14
|
+
"oxfmt": "^0.19",
|
|
15
|
+
"oxlint": "^1.34",
|
|
16
16
|
"rolldown": "1.0.0-beta.55",
|
|
17
17
|
"tslib": "^2.8",
|
|
18
18
|
"typescript": "^5.9",
|
|
@@ -64,11 +64,11 @@
|
|
|
64
64
|
"build": "npm run clean && npx vite build && npm run rolldown:build && npx tsc",
|
|
65
65
|
"clean": "rm -rf ./dist && rm -rf ./types && rm -f ./tsconfig.tsbuildinfo",
|
|
66
66
|
"rolldown:build": "npx rolldown -c",
|
|
67
|
-
"rolldown:watch": "npx rolldown -c --watch",
|
|
67
|
+
"rolldown:watch": "npx rolldown -c ./rolldown.config.js --watch",
|
|
68
68
|
"test": "npx vitest --coverage",
|
|
69
69
|
"watch": "npx vite build --watch"
|
|
70
70
|
},
|
|
71
71
|
"type": "module",
|
|
72
72
|
"types": "types/index.d.ts",
|
|
73
|
-
"version": "0.
|
|
73
|
+
"version": "0.39.0"
|
|
74
74
|
}
|
package/src/constants.ts
CHANGED
|
@@ -1,39 +1,7 @@
|
|
|
1
|
+
import FRAME_RATE_MS from '@oscarpalmer/atoms/frame-rate';
|
|
1
2
|
import type {TimerType, WorkHandlerType} from './models';
|
|
2
3
|
import type {Timer} from './timer';
|
|
3
4
|
|
|
4
|
-
function calculate(): Promise<number> {
|
|
5
|
-
return new Promise(resolve => {
|
|
6
|
-
const values: number[] = [];
|
|
7
|
-
|
|
8
|
-
let last: DOMHighResTimeStamp | undefined;
|
|
9
|
-
|
|
10
|
-
function step(now: DOMHighResTimeStamp): void {
|
|
11
|
-
if (last != null) {
|
|
12
|
-
values.push(now - last);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
last = now;
|
|
16
|
-
|
|
17
|
-
if (values.length >= 10) {
|
|
18
|
-
const median =
|
|
19
|
-
values
|
|
20
|
-
.sort()
|
|
21
|
-
.slice(2, -2)
|
|
22
|
-
.reduce((first, second) => first + second, 0) /
|
|
23
|
-
(values.length - 4);
|
|
24
|
-
|
|
25
|
-
resolve(median);
|
|
26
|
-
} else {
|
|
27
|
-
requestAnimationFrame(step);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
requestAnimationFrame(step);
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
//
|
|
36
|
-
|
|
37
5
|
/**
|
|
38
6
|
* Buffer value to use when evaluating if a specific time is within a certain range
|
|
39
7
|
*/
|
|
@@ -77,13 +45,4 @@ export const WORK_START: WorkHandlerType = 'start';
|
|
|
77
45
|
|
|
78
46
|
export const WORK_STOP: WorkHandlerType = 'stop';
|
|
79
47
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* A calculated average of the refresh rate of the display _(in milliseconds)_
|
|
84
|
-
*/
|
|
85
|
-
export let MILLISECONDS = 1000 / 60;
|
|
86
|
-
|
|
87
|
-
calculate().then(value => {
|
|
88
|
-
MILLISECONDS = value;
|
|
89
|
-
});
|
|
48
|
+
export {FRAME_RATE_MS};
|
package/src/delay.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {BUFFER_INTERVAL,
|
|
1
|
+
import {BUFFER_INTERVAL, FRAME_RATE_MS} from './constants';
|
|
2
2
|
import {getValidNumber} from './get';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -8,14 +8,14 @@ import {getValidNumber} from './get';
|
|
|
8
8
|
*/
|
|
9
9
|
export function delay(time?: number): Promise<void> {
|
|
10
10
|
return new Promise(resolve => {
|
|
11
|
-
const interval = getValidNumber(time,
|
|
11
|
+
const interval = getValidNumber(time, FRAME_RATE_MS);
|
|
12
12
|
|
|
13
13
|
let start: DOMHighResTimeStamp;
|
|
14
14
|
|
|
15
15
|
function step(now: DOMHighResTimeStamp) {
|
|
16
16
|
start ??= now;
|
|
17
17
|
|
|
18
|
-
if (interval ===
|
|
18
|
+
if (interval === FRAME_RATE_MS || now - start >= interval - BUFFER_INTERVAL) {
|
|
19
19
|
resolve();
|
|
20
20
|
} else {
|
|
21
21
|
requestAnimationFrame(step);
|
package/src/repeat.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {FRAME_RATE_MS, TYPE_REPEAT} from './constants';
|
|
2
2
|
import {getCallback, getValidNumber} from './get';
|
|
3
3
|
import './global';
|
|
4
4
|
import {type RepeatOptions, TimerTrace} from './models';
|
|
@@ -21,7 +21,7 @@ export function repeat(callback: (index: number) => void, options?: Partial<Repe
|
|
|
21
21
|
onAfter: getCallback(options?.onAfter),
|
|
22
22
|
onError: getCallback(options?.onTimeout),
|
|
23
23
|
count: getValidNumber(options?.count),
|
|
24
|
-
interval: getValidNumber(options?.interval,
|
|
24
|
+
interval: getValidNumber(options?.interval, FRAME_RATE_MS),
|
|
25
25
|
timeout: getValidNumber(options?.timeout),
|
|
26
26
|
},
|
|
27
27
|
true,
|
package/src/timer.ts
CHANGED
package/src/wait.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {FRAME_RATE_MS, TYPE_WAIT} from './constants';
|
|
2
2
|
import {getCallback, getValidNumber} from './get';
|
|
3
3
|
import './global';
|
|
4
4
|
import {TimerTrace} from './models';
|
|
@@ -20,7 +20,7 @@ export function wait(callback: () => void, time?: number): Timer {
|
|
|
20
20
|
onAfter: undefined,
|
|
21
21
|
onError: undefined,
|
|
22
22
|
count: -1,
|
|
23
|
-
interval: getValidNumber(time,
|
|
23
|
+
interval: getValidNumber(time, FRAME_RATE_MS),
|
|
24
24
|
timeout: 0,
|
|
25
25
|
},
|
|
26
26
|
true,
|
package/src/when.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {noop} from '@oscarpalmer/atoms/function';
|
|
2
|
-
import {
|
|
2
|
+
import {FRAME_RATE_MS, MESSAGE_DESTROYED, MESSAGE_STARTED, TYPE_WHEN} from './constants';
|
|
3
3
|
import {getValidNumber, getValidTimeout} from './get';
|
|
4
4
|
import './global';
|
|
5
5
|
import {TimerTrace, type WhenOptions, type WhenState} from './models';
|
|
6
6
|
import {Timer} from './timer';
|
|
7
7
|
|
|
8
8
|
class When {
|
|
9
|
-
private readonly $timer
|
|
9
|
+
private declare readonly $timer: string;
|
|
10
10
|
|
|
11
11
|
private readonly state: WhenState = {
|
|
12
12
|
promise: undefined as never,
|
|
@@ -45,6 +45,10 @@ class When {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
constructor(condition: () => boolean, options?: Partial<WhenOptions>) {
|
|
48
|
+
Object.defineProperty(this, '$timer', {
|
|
49
|
+
value: TYPE_WHEN,
|
|
50
|
+
});
|
|
51
|
+
|
|
48
52
|
const {state} = this;
|
|
49
53
|
|
|
50
54
|
state.promise = new Promise<void>((resolve, reject) => {
|
|
@@ -86,7 +90,7 @@ class When {
|
|
|
86
90
|
this.destroy();
|
|
87
91
|
},
|
|
88
92
|
count: getValidNumber(options?.count),
|
|
89
|
-
interval: getValidNumber(options?.interval,
|
|
93
|
+
interval: getValidNumber(options?.interval, FRAME_RATE_MS),
|
|
90
94
|
timeout: getValidTimeout(options?.timeout),
|
|
91
95
|
},
|
|
92
96
|
false,
|
package/src/work.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TIMERS_ACTIVE,
|
|
3
3
|
BUFFER_INTERVAL,
|
|
4
|
-
|
|
4
|
+
FRAME_RATE_MS,
|
|
5
5
|
TYPE_WAIT,
|
|
6
6
|
WORK_CONTINUE,
|
|
7
7
|
WORK_PAUSE,
|
|
@@ -84,7 +84,7 @@ function run(
|
|
|
84
84
|
return;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
if (options.interval ===
|
|
87
|
+
if (options.interval === FRAME_RATE_MS || state.elapsed >= options.interval - BUFFER_INTERVAL) {
|
|
88
88
|
if (options.count > -1) {
|
|
89
89
|
(state.callback as (index: number) => void)(state.index);
|
|
90
90
|
}
|
package/types/constants.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import FRAME_RATE_MS from '@oscarpalmer/atoms/frame-rate';
|
|
1
2
|
import type { TimerType, WorkHandlerType } from './models';
|
|
2
3
|
import type { Timer } from './timer';
|
|
3
4
|
/**
|
|
@@ -29,7 +30,4 @@ export declare const WORK_PAUSE: WorkHandlerType;
|
|
|
29
30
|
export declare const WORK_RESTART: WorkHandlerType;
|
|
30
31
|
export declare const WORK_START: WorkHandlerType;
|
|
31
32
|
export declare const WORK_STOP: WorkHandlerType;
|
|
32
|
-
|
|
33
|
-
* A calculated average of the refresh rate of the display _(in milliseconds)_
|
|
34
|
-
*/
|
|
35
|
-
export declare let MILLISECONDS: number;
|
|
33
|
+
export { FRAME_RATE_MS };
|