r-util-js/packages/common/src/timer/TimeoutTimer.ts

139 lines
4.1 KiB
TypeScript
Raw Normal View History

2026-03-16 17:58:57 +08:00
type TimerCallback = (time: number) => void;
/**
*
*
* startTime endTime
* interval endTime
*
* Countdown TimeoutTimer 使 dayjs duration
*
*
* @example
* ```ts
* // 实例方式
* const timer = new TimeoutTimer(10, 0, 1000)
* timer.addStepEventListener((time) => console.log('剩余:', time))
* timer.addCountdownEventListener((time) => console.log('结束:', time))
* timer.start()
*
* // 静态工厂方式
* const timer2 = TimeoutTimer.start(10, 0, 1000,
* (time) => console.log('剩余:', time),
* (time) => console.log('结束:', time),
* )
* ```
*/
2026-03-16 17:58:57 +08:00
export default class TimeoutTimer {
/** 起始时间(数值) */
2026-03-16 17:58:57 +08:00
startTime = 0;
/** 结束时间(数值),倒计时到此值停止 */
2026-03-16 17:58:57 +08:00
endTime = 0;
/** 递减间隔(毫秒) */
2026-03-16 17:58:57 +08:00
interval = 0;
/** 当前剩余时间 */
2026-03-16 17:58:57 +08:00
time = 0;
/** 定时器 ID-1 表示未运行 */
2026-03-16 17:58:57 +08:00
id = -1;
/** 步骤监听器列表,每次递减时触发,参数为当前剩余时间 */
2026-03-16 17:58:57 +08:00
stepEventListenerList = <TimerCallback[]>[];
/** 完成监听器列表,倒计时结束时触发,参数为结束时间 */
2026-03-16 17:58:57 +08:00
countdownEventListenerList = <TimerCallback[]>[];
/**
* @param startTime
* @param endTime 0
* @param interval 1000
2026-03-16 17:58:57 +08:00
*/
constructor(startTime = 5, endTime = 0, interval = 1000) {
this.startTime = startTime;
this.endTime = endTime;
this.interval = interval;
}
/**
*
*
*
*
* @param cb
* @returns cb TypeError
2026-03-16 17:58:57 +08:00
*/
addStepEventListener(cb: TimerCallback) {
if (!(cb instanceof Function)) {
return new TypeError("回调函数类型错误: cb: " + cb);
}
this.stepEventListenerList.push(cb);
}
/**
*
*
* endTime
*
* @param cb
* @returns cb TypeError
2026-03-16 17:58:57 +08:00
*/
addCountdownEventListener(cb: TimerCallback) {
if (!(cb instanceof Function)) {
return new TypeError("回调函数类型错误: cb: " + cb);
}
this.countdownEventListenerList.push(cb);
}
/**
*
*
* @param startTime
* @param endTime 0
* @param interval 1000
* @param stepEventListener
* @param countdownEventListener
* @returns TimeoutTimer start
2026-03-16 17:58:57 +08:00
*/
static start(
startTime: number,
endTime: number = 0,
interval = 1000,
stepEventListener?: TimerCallback,
countdownEventListener?: TimerCallback,
) {
const timer = new TimeoutTimer(startTime, endTime, interval);
if (stepEventListener != null) {
timer.addStepEventListener(stepEventListener);
}
if (countdownEventListener != null) {
timer.addCountdownEventListener(countdownEventListener);
}
return timer;
}
/**
* startTime endTime
2026-03-16 17:58:57 +08:00
*/
start() {
this.time = this.startTime;
this.id = window.setInterval(() => {
this.time -= this.interval;
console.log(this.time);
this.stepEventListenerList.forEach((cb) => cb(this.time));
if (this.time <= this.endTime && this.id !== -1) {
this.stop();
}
}, this.interval);
}
/**
*
2026-03-16 17:58:57 +08:00
*/
stop() {
console.log("stop", this.id);
clearInterval(this.id);
this.id = -1;
this.time = this.endTime;
this.countdownEventListenerList.forEach((cb) => cb(this.time));
}
}