addons/isl/src/timer.tsblame
View source
b69ab311/**
b69ab312 * Copyright (c) Meta Platforms, Inc. and affiliates.
b69ab313 *
b69ab314 * This source code is licensed under the MIT license found in the
b69ab315 * LICENSE file in the root directory of this source tree.
b69ab316 */
b69ab317
b69ab318import type {Disposable} from './types';
b69ab319
b69ab3110export class Timer implements Disposable {
b69ab3111 private timerId: null | number = null;
b69ab3112 private disposed = false;
b69ab3113 private callback: () => void;
b69ab3114
b69ab3115 /**
b69ab3116 * The `callback` can return `false` to auto-stop the timer.
b69ab3117 * The timer auto stops if being GC-ed.
b69ab3118 */
b69ab3119 constructor(
b69ab3120 callback: () => void | boolean,
b69ab3121 public intervalMs = 1000,
b69ab3122 enabled = false,
b69ab3123 ) {
b69ab3124 const thisRef = new WeakRef(this);
b69ab3125 this.callback = () => {
b69ab3126 const timer = thisRef.deref();
b69ab3127 if (timer == null) {
b69ab3128 // The "timer" object is GC-ed. Do not run this interval.
b69ab3129 return;
b69ab3130 }
b69ab3131 // Run the callback and schedules the next interval.
b69ab3132 timer.timerId = null;
b69ab3133 const shouldContinue = callback();
b69ab3134 if (shouldContinue !== false) {
b69ab3135 timer.enabled = true;
b69ab3136 }
b69ab3137 };
b69ab3138 this.enabled = enabled;
b69ab3139 }
b69ab3140
b69ab3141 set enabled(value: boolean) {
b69ab3142 if (value && this.timerId === null && !this.disposed) {
b69ab3143 this.timerId = window.setTimeout(this.callback, this.intervalMs);
b69ab3144 } else if (!value && this.timerId !== null) {
b69ab3145 window.clearTimeout(this.timerId);
b69ab3146 this.timerId = null;
b69ab3147 }
b69ab3148 }
b69ab3149
b69ab3150 get enabled(): boolean {
b69ab3151 return this.timerId !== null;
b69ab3152 }
b69ab3153
b69ab3154 dispose(): void {
b69ab3155 this.enabled = false;
b69ab3156 this.disposed = true;
b69ab3157 }
b69ab3158}