type ICallback = ( t : number ) => void ; export default class Ticker { private _scheduledForThisOrNextTick : Set < ICallback > ; private _scheduledForNextTick : Set < ICallback > ; private _timeAtCurrentTick : number ; private _ticking : boolean = false ; constructor ( ) { this . _scheduledForThisOrNextTick = new Set ( ) ; this . _scheduledForNextTick = new Set ( ) ; this . _timeAtCurrentTick = 0 ; } /**
     * Registers for fn to be called either on this tick or the next tick.
     *
     * If registerSideEffect() is called while Ticker.tick() is running, the
     * side effect _will_ be called within the running tick. If you don't want this
     * behavior, you can use registerSideEffectForNextTick().
     *
     * Note that fn will be added to a Set(). Which means, if you call registerSideEffect(fn)
     * with the same fn twice in a single tick, it'll only run once.
     */ onThisOrNextTick ( fn ) { this . _scheduledForThisOrNextTick . add ( fn ) ; } see Ticker onNextTick ( fn ) { this . _scheduledForNextTick . add ( fn ) ; } offThisOrNextTick ( fn ) { this . _scheduledForThisOrNextTick . delete ( fn ) ; } offNextTick ( fn ) { this . _scheduledForNextTick . delete ( fn ) ; } get time ( ) { if ( this . _ticking ) { return this . _timeAtCurrentTick ; } else return performance . now ( ) ; } tick ( t = performance . now ( ) ) { this . _ticking = true ; this . _timeAtCurrentTick = t ; this . _scheduledForNextTick . forEach ( ( v ) => this . _scheduledForThisOrNextTick . add ( v ) ) ; this . _scheduledForNextTick . clear ( ) ; this . _tick ( 0 ) ; this . _ticking = false ; } private _tick ( iterationNumber ) { const time = this . time ; if ( iterationNumber > 10 ) { console . warn ( '_tick() recursing for 10 times' ) ; } if ( iterationNumber > 100 ) { throw new Error ( `Maximum recursion limit for _tick()` ) ; } const oldSet = this . _scheduledForThisOrNextTick ; this . _scheduledForThisOrNextTick = new Set ( ) ; oldSet . forEach ( ( fn ) => { fn ( time ) ; } ) ; if ( this . _scheduledForThisOrNextTick . size > 0 ) { return this . _tick ( iterationNumber + 1 ) ; } } }