@@ -14,14 +14,19 @@ export type TickEventsHandler<K extends TickEvents> = TickEventHandlers[K]
1414
1515// This update loop ensures that each update() is called one at a time, even if it takes longer than the interval
1616export class Ticker extends EventEmitter < TickEventHandlers > {
17+ private stopping = false
18+ private initialTimer : ReturnType < typeof setTimeout > | null = null
19+
1720 constructor ( options ?: { interval ?: number } ) {
1821 super ( )
1922 const { interval = 300 } = options ?? { interval : 300 }
2023
2124 let last = Date . now ( )
2225
23- setTimeout ( async ( ) => {
24- while ( true ) {
26+ this . initialTimer = setTimeout ( async ( ) => {
27+ this . initialTimer = null
28+
29+ while ( ! this . stopping ) {
2530 const start = Date . now ( )
2631 const nextTickPromise = new Promise < void > ( ( resolve ) => {
2732 // Schedule nextTick resolution for after all callbacks complete
@@ -43,7 +48,7 @@ export class Ticker extends EventEmitter<TickEventHandlers> {
4348 ] )
4449
4550 const remaining = interval - ( Date . now ( ) - start )
46- if ( remaining > 0 )
51+ if ( remaining > 0 && ! this . stopping )
4752 await new Promise ( resolve => setTimeout ( resolve , remaining ) )
4853
4954 last = start
@@ -54,4 +59,15 @@ export class Ticker extends EventEmitter<TickEventHandlers> {
5459 on < K extends TickEvents > ( event : K , cb : TickEventsHandler < K > ) {
5560 return super . on ( event , cb )
5661 }
62+
63+ stop ( ) {
64+ this . stopping = true
65+
66+ if ( this . initialTimer ) {
67+ clearTimeout ( this . initialTimer )
68+ this . initialTimer = null
69+ }
70+
71+ this . removeAllListeners ( )
72+ }
5773}
0 commit comments