Con TypeScript, he estado tratando de configurar lo que llamo un "disparador": un objeto que contiene una función de verificación (devuelve un booleano) y una función de comportamiento , que puede hacer básicamente cualquier cosa. Lo que quiero hacer es cada vez que se cambia el valor de una determinada variable, se ejecuta la función de verificación del disparador y, si devuelve verdadero, también se ejecuta la función de comportamiento .
Naturalmente, puse la llamada a la función de verificación del disparador en un setter:
set health(value: number) { this._health = value; runTriggers(); }El objetivo de la función de comportamiento de un disparador es hacer cualquier cosa, pero principalmente cambiar los valores de las variables . Y ahí es donde está el problema: si se llama a un disparador en el setter de salud como el anterior, y la función de comportamiento del disparador también cambia la variable de salud (llamando así al setter nuevamente), terminará en una llamada recursiva infinita.
¿Cómo podría evitar que suceda esta llamada infinita, al mismo tiempo que permito que la función de comportamiento de mi disparador cambie libremente las variables?
Es probable que la solución dependa mucho de sus elecciones generales de diseño. Fundamentalmente, debe tener una manera de decir "no haga un ciclo infinito", lo que significa que en algún lugar, en algún momento, algo tendrá que poder establecer health sin ejecutar disparadores.
Una bandera simple le permitiría evitar incluso una llamada de activación recursiva:
set health(value: number) { this._health = value; if (!this._healthTriggerActive) { this._healthTriggerActive = true; try { runTriggers(); } finally { this._healthTriggerActive = false; } } } ... pero eso, por supuesto, significa que establecer health en una devolución de llamada de activación no ejecutará activadores (ya que ese es el problema básico).
También puede limitar la profundidad con un contador, lo que permite una cierta cantidad de recurrencia, pero no demasiada; pero eso probablemente solo esté ocultando el problema.