-
Notifications
You must be signed in to change notification settings - Fork 4
/
time.js
88 lines (78 loc) · 2.3 KB
/
time.js
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import { global } from 'source/env/global'
const tryClock = () => {
try { // browser
const { performance } = global
const clock = () => performance.now()
const time = clock()
if (time <= clock()) return clock
} catch (error) { __DEV__ && console.log('[tryClock] browser', error) }
try { // node
const { process } = global
const clock = () => {
const [ seconds, nanoseconds ] = process.hrtime()
return seconds * 1000 + nanoseconds * 0.000001
}
const time = clock()
if (time <= clock()) return clock
} catch (error) { __DEV__ && console.log('[tryClock] node', error) }
return Date.now // last fallback
}
const CLOCK_PER_SECOND = 1000
const CLOCK_TO_SECOND = 1 / CLOCK_PER_SECOND
const clock = tryClock() // return running/relative time in milliseconds
const getTimestamp = () => Math.floor(Date.now() * CLOCK_TO_SECOND) // UTC, integer
// NOTE: no way to cancel the timeout, may keep node running longer than expected
// Usage:
// const getData = async () => {
// await setTimeoutAsync(500)
// return 'DATA'
// }
const setTimeoutAsync = (wait = 0) => new Promise((resolve) => setTimeout(resolve, wait))
const [ requestFrameUpdate, cancelFrameUpdate ] = global.requestAnimationFrame
? [ global.requestAnimationFrame, global.cancelAnimationFrame ]
: [ (func) => setTimeout(func, 1000 / 60), clearTimeout ]
const createTimer = ({
func,
delay,
queueTask = setTimeout,
cancelTask = clearTimeout
}) => {
let token = null
const update = () => {
if (!token) return
token = queueTask(update, delay)
func()
}
const start = () => { if (!token) token = queueTask(update, delay) }
const stop = () => {
if (!token) return
cancelTask(token)
token = null
}
const isActive = () => Boolean(token)
const getDelay = () => delay
const setDelay = (nextDelay) => {
if (nextDelay === delay) return // skip same delay
delay = nextDelay
stop()
start()
}
return { start, stop, isActive, getDelay, setDelay }
}
const createStepper = (prevTime = clock()) => () => {
const nextTime = clock()
const result = nextTime - prevTime
prevTime = nextTime
return result
}
export {
CLOCK_PER_SECOND,
CLOCK_TO_SECOND,
clock,
getTimestamp,
setTimeoutAsync,
requestFrameUpdate,
cancelFrameUpdate,
createTimer,
createStepper
}