blob: 4c344e36f4e541de168427fb2462439d6d73b5dc [file] [log] [blame]
Copybara botbe50d492023-11-30 00:16:42 +01001const MIN_INERVAL = 1000/60;
2
3/**
4 * Trigger a callback at a given interval
5 * @param interval defaults to 1000/60 ms
6 * @return {function()} reference to start, stop, immediate and started
7 */
8
9const intervalFunction = ( interval = MIN_INERVAL ) => {
10
11 let lapse = interval < MIN_INERVAL ? MIN_INERVAL : interval;
12 let cb = undefined;
13 let next = null;
14 let timeElapsed = 0;
15
16 const execute = () => {
17 const f = cb(timeElapsed);
18 if (!f) {
19 cancel();
20 }
21 };
22
23 const cancel = () => {
24 if(next) {
25 window.cancelAnimationFrame(next);
26 }
27 next = null;
28 timeElapsed = 0;
29 };
30
31 const start = () => {
32 let timeStart = Date.now();
33
34 const loop = now => {
35 if (next) {
36 next = window.requestAnimationFrame( () => loop( Date.now() ));
37
38 timeElapsed += now - timeStart;
39
40 if(timeElapsed >= lapse) {
41 execute();
42 if( (timeElapsed -= lapse) > lapse) {
43 // time elapsed - interval_ > interval_ , indicates inactivity
44 // Could be due to browser minimized, tab changed, screen saver started, computer sleep, and so on
45 timeElapsed = 0;
46 }
47 }
48 timeStart = now;
49 }
50 };
51
52 next = 1; // a truthy value for first loop
53 loop( timeStart );
54 };
55
56 return {
57 get started() {
58 return next != null;
59 },
60 get interval() {
61 return lapse;
62 },
63 set interval(value) {
64 lapse = value < MIN_INERVAL ? MIN_INERVAL : value;
65 },
66 start(callback) {
67 if(typeof callback !== 'function') {
68 throw new TypeError('callback parameter must be a function');
69 }
70 cb = callback;
71 start();
72 },
73 immediate() {
74 if(!cb) {
75 throw new ReferenceError('callback parameter is not defined. Call start before immediate.');
76 }
77 execute();
78 },
79 stop: () => cancel(),
80 };
81};
82
83export default intervalFunction;