-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
54 lines (48 loc) · 1.6 KB
/
index.ts
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
type NonEmptyArray<T> = T[] & { 0: T };
/**
* Wait for a queue of sequential timers to complete before calling
* a callback. Returns cancellation function to abort queue.
* @param timerQueue Array of timers:
* - "raf" -> requestAnimationFrame
* - "ric" -> requestIdleCalback
* - {number} -> setTimeout
* @param onComplete Called after queue of timers completes
* @returns Cancellation function that can be called to abort queue
*/
export default function waitForTimers(
timerQueue: NonEmptyArray<'raf' | 'ric' | number>,
onComplete: Function
): () => void {
// Cancel current timer (gets overridden as timer changes)
let cancelTimer = () => {};
// Process first timer in queue
nextTimer(0);
return () => cancelTimer();
function nextTimer(index: number) {
// All timers have completed
if (index >= timerQueue.length) return onComplete();
const timer = timerQueue[index];
const startNextTimer = () => nextTimer(++index);
if (typeof timer === 'number') {
cancelTimer = getTimers().timeout(startNextTimer, timer);
} else {
cancelTimer = getTimers()[timer](startNextTimer);
}
}
function getTimers() {
return {
raf: (fn: () => void) => {
const rafId = requestAnimationFrame(fn);
return () => cancelAnimationFrame(rafId);
},
ric: (fn: () => void) => {
const ricId = requestIdleCallback(fn);
return () => cancelIdleCallback(ricId);
},
timeout: (fn: () => void, timeoutMs: number) => {
const timeoutId = setTimeout(fn, timeoutMs);
return () => clearTimeout(timeoutId);
},
};
}
}