我正在参加「掘金·启航计划」
useKeepInterval
我们一般会使用 setTimeout
和 setInterval
用来做倒计时和计时的操作,而如果我想要暂停这个操作就需要执行 clearTimeout
和 clearInterval
, 但是如果我想要基于上一次暂停的剩余时间,继续开始倒计时,这就需要再进一步的处理了。
因此这个可以(暂停 / 继续)并保留剩余倒计时的计时器钩子就诞生了。
demo预览
实现过程
数据定义
定义一个 useRef
其中保存以下数据。
-
timeout: 用于保存最外层的
setTimeout
-
interval: 保存的内层的
setInterval
-
cur: 记录当前时间
-
end: 记录暂停时间
-
fn: 传入的执行函数
-
intervalTime: 固定的时间间隔
-
remainTime: 用于
setTimeout
的剩余时间间隔
const timerRef = useRef<TimerType>({
timeout: null,
interval: null,
cur: 0,
end: 0,
fn: undefined,
intervalTime: 0,
remainTime: 0
})
开始计时器
传入执行函数,间隔时间,即可开始一个根据倒计时运行的函数(中途可以暂停和继续)。
实现过程主要是将传递进来的函数,间隔时间等记录下来,然后通过一个 setTimeout
包裹住 setInterval
并在其中穿插执行函数,同时需要记录并处理开始暂停等操作的时间即可。
/**
* 设置/开启计时器
* @param fn 执行函数
* @param intervalTime 间隔时间
* @param isInit 是否是初始化设置计时器
*/
const set = (fn?: () => void, intervalTime?: number, isInit = false) => {
const timeItem = timerRef.current
if(fn) {
timeItem.fn = fn
}
if(intervalTime) {
timeItem.intervalTime = intervalTime
timeItem.remainTime = intervalTime
}
if(isInit) return
stopTime()
timeItem.remainTime -= timeItem.end - timeItem.cur
timeItem.cur = Date.now()
timeItem.end = timeItem.cur
timeItem.timeout = setTimeout(() => {
timeItem.cur = Date.now()
timeItem.end = timeItem.cur
timeItem.remainTime = timeItem.intervalTime
timeItem.interval = setInterval(() => {
timeItem.cur = Date.now()
timeItem.end = timeItem.cur
timeItem.fn!()
}, timeItem.intervalTime)
timeItem.fn!()
}, timeItem.remainTime)
}
暂停计时器
清除计时器和记录暂停的时间,用于重新开始计时器时,计算剩余时间;
/** 关闭计时器 */
const pause = () => {
timerRef.current.end = Date.now()
stopTime()
return timerRef.current.end - timerRef.current.cur
}
/** 停止定时器 */
const stopTime = () => {
clearTimeout(timerRef.current.timeout!)
clearInterval(timerRef.current.interval!)
timerRef.current.timeout = null
timerRef.current.interval = null
}
© 版权声明
文章版权归作者所有,未经允许请勿转载,侵权请联系 admin@trc20.tw 删除。
THE END