¿Debería llamarse a un oyente de eventos si está conectado después de que el evento ya se haya disparado?


8

¿Debe llamarse a un oyente de eventos si está conectado después de que el evento ya se haya disparado? ¿Qué pasa si el evento solo se disparará una vez?

El primer ejemplo que viene a la mente es el readyevento en jQuery. El siguiente fragmento, cuando se evalúa después de que la página se ha cargado, seguirá llamando a la devolución de llamada:

$(document).ready(function () {
    console.log("Works.");
});

La alternativa a este comportamiento podría ser un indicador que se establece cuando se carga la página, lo que obliga al consumidor de la API a verificar si el evento ya sucedió y actuar en consecuencia:

if (document.readyState == "complete") {
    console.log("Works.");
} else {
    $(document).ready(function () {
        console.log("Works.");
    });
}

Si bien el ejemplo anterior está en el contexto de una página web que se carga donde cualquier cosa y todo (generalmente) debe suceder después de que la página se haya cargado por completo, se podrían hacer los mismos argumentos para cualquier componente individual en una aplicación, que tiene eventos "únicos" ( load, start, end, etc.). Un ejemplo de un solo componente podría ser un mapa con un loadevento que se dispara para especificar que el mapa que se ha cargado :

map.on("load", function () {
    console.log("The map has loaded.");
});

El ejemplo anterior proviene de la API de ArcGIS para JavaScript, donde ese evento se dispara solo una vez, y si un consumidor "espera" que el mapa se cargue después de que el mapa ya esté cargado, nunca se llamará al oyente. El resultado deseado requiere verificar el estado del mapa antes de que se adjunte el oyente:

if (map.loaded) {
    console.log("The map has loaded.");
} else {
    map.on("load", function () {
        console.log("The map has loaded.");
    });
}

¿Qué comportamiento es correcto, que requiere que el consumidor verifique si un evento ya se ha activado o siempre está llamando a la devolución de llamada?


55
Es posible que esté interesado en Reactive Extensions ' Subjectvs. ReplaySubject, donde este último reproduce eventos anteriores para suscriptores tardíos, mientras que el primero no. Es decir, los creadores de Rx modelaron ambos comportamientos en lugar de decidir sobre un comportamiento definido. - Y aunque los enlaces anteriores van a la documentación de la versión .NET de Rx, también hay un Rx para JavaScript .
stakx

Respuestas:


19

Eso depende de si se trata realmente de un evento o una notificación de estado (que es lo que está listo). Si es un evento, entonces no le dice al oyente acerca de todos los eventos anteriores. Si se trata de una Notificación de estado, usted les informa inmediatamente después de que se hayan suscrito y se encuentre en el estado especificado.

Lo difícil será dónde puede ser un estado o un evento, dependiendo de cómo lo veas, en el peor de los casos, eso se explica en la documentación. En el mejor de los casos, elige un buen nombre que deja en claro a qué se refiere.


2
+1, también por mencionar notificaciones de estado. Las notificaciones estatales son IMO cercanas a futuros y su manejo de devoluciones de llamada, por ejemplo, en Scala ( docs.scala-lang.org/overviews/core/futures.html ).
Giorgio

Interesante, no lo había pensado así. ¿Clasificaría load, starto endlo mismo que ready, como una notificación de estado?
Whymarrh

@Whymarrh: Eso dependerá del contexto, pero a mí me parecen eventos. Tendería a nombrar notificaciones estatales como preguntas ... ¿listo? ¿empezado? ¿corriendo? pero, por supuesto, es posible que deba adaptarlo a una convención de nomenclatura existente.
jmoreno

3
Me parece que los eventos pueden interpretarse como algo que ocurre una vez para cambiar el estado. Esto significa que tienen una vida muy corta, prácticamente un solo momento. Un estado por otro lado tiene una vida más larga y consta de múltiples momentos. loadNo es un evento ni un estado. loadingStartedEs un evento y loadinges un estado.
Jeroen Vannevel

5

En general, no .

No se debe llamar a los oyentes de eventos si están conectados después de que el evento ya se haya activado. "Si te duermes tu pierdes."

Hay algunas excepciones importantes. $(document).ready()es quizás el ejemplo perfecto: un evento antes del cual el contexto de evaluación completo no está establecido de manera confiable o completa, y que sirve como un marcador de "el procesamiento completo de la función comienza aquí".

Sin embargo, si establece la regla de que se debe activar un controlador de eventos incluso si está instalado y / o activado después de que ocurra el evento, entonces ha declarado que todos los eventos deben o deben almacenarse desde el principio hasta el final de la ejecución del programa, para cada evento concebible. De lo contrario, puede haber controladores de eventos establecidos en algún evento, en algún lugar en el futuro, que no tiene suficiente información para saber si debe disparar cuando se establece. Eso significa que tendrías que instrumentar cada posible fuente de eventos y almacenar infinitamente cada uno de ellos también. Eso lleva el procesamiento de eventos desde una evaluación perezosa (y todos sus beneficios de rendimiento) hasta una evaluación entusiastay sobre lo que esté en el otro extremo del espectro. ¿Evaluación frenética basada en suposiciones catastróficas sobre qué eventos podrían necesitar ser manejados más tarde?

Los eventos tienden a ser transitorios y numerosos. Establecer reglas que requieran que cada uno se proteja, sin limitación, sobre la posibilidad de que eventualmente se aprovechen: es un suicidio de rendimiento. Además, no hay un gran requisito para hacerlo, ya que los controladores generalmente se pueden establecer temprano en la vida del programa.

Las excepciones a la regla son casos extremos: cargas de documentos o subsistemas, por ejemplo, que son eventos esenciales, únicos y principales que de otro modo no son capturables o manejables. Esto está muy cerca de sus eventos "singleton". Otro grupo que podría necesitar un manejo especial son los errores significativos, los eventos de seguridad o los cambios de estado que tienen una necesidad excepcional de marcarse, incluso si no hay suscriptores a la bandera en el momento en que ocurrió el evento.

Una nota final: un evento "listo" es sutilmente diferente de un evento de "carga". Si bien a menudo no se distinguen claramente (por ejemplo, HTML onloady jQuery se $(document).ready()consideran lógicamente muy similares), y ambos indican la disponibilidad de un recurso o entorno de procesamiento, pero no son exactamente lo mismo. La carga (o el final de la misma) es un verdadero evento, algo señalado desde la infraestructura hasta el consumidor. La preparación, sin embargo, es más la citade la infraestructura que carga el recurso / entorno y que el consumidor está listo para consumir / aprovechar esa disponibilidad. La preparación viene después de la carga, y es uno de esos eventos especiales designados / puntos de coordinación que deben tratarse como en cola porque no puede capturarlo de otra manera. Sin embargo, el hecho de que existan algunos casos muy especiales no significa que cada evento deba ser activable a posteriori .


Erm, ¿te referías a "onload" de html?
StarWeaver

@StarWeaver Gracias. No estoy seguro si me resbalé o si mi autocorrección demasiado ambiciosa lo hizo, pero tienes toda la razón. Fijo.
Jonathan Eunice

NP, no estoy del todo con el html post 4 pero sonaba extraño. Buena explicación, también.
StarWeaver
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.