¿Puedes hacerme entender fácilmente objetos dinámicos y abstractos de eventos?

StackOverflow https://stackoverflow.com/questions/471144

  •  19-08-2019
  •  | 
  •  

Pregunta

He escrito aplicaciones controladas por eventos de C ++ usando MFC para botones GUI, y uso eventos HTML como onmousedown para activar Javascript en una página web. La idea de la programación basada en eventos es intuitiva cuando se utiliza la interfaz y los eventos están codificados.

Sé cómo usar un puntero de función en C, y veo cómo Windows los usa para ejecutar un bucle de eventos. Puedo escribir código para llamar dinámicamente una función diferente.

Mi problema es alejarme del tiempo de compilación y pasar al tiempo de ejecución. Estoy hablando de cualquier idioma aquí, pero si necesita un idioma, elija Javascript o PHP, ya que los uso más estos días. No entiendo cómo puedo usar mi propio objeto de evento para hacer algo. Simplemente no es un concepto que entiendo. Y como no los uso, no sé cuál podría ser su uso práctico.

Por ejemplo, supongo que si quisiera hacer un juego por turnos personalizado, podría usar objetos de evento para representar un efecto de alguna habilidad de pieza de juego que solo necesita "suceder".

¿Puede alguien darme un uso simple de eventos personalizados? ¿O situaciones en las que es útil o práctico? ¿Depende en gran medida del idioma y el entorno y de cómo se manejan los eventos? Una respuesta Javascript sería buena, pero leo muchos idiomas.

Lo siento, soy deficiente en este aspecto y necesito una visión práctica, avanzada (¿intermedia?). Es como punteros en C. I '' obtengo '' punteros y cómo son tus amigos. Pero hubo un tiempo en que no lo hice, y muchas personas que conozco aún no lo hacen. Es simple una vez que lo obtienes, simplemente no obtengo eventos dinámicos personalizados de esa manera.

¿Fue útil?

Solución

Cuando hablamos de programación orientada a eventos, generalmente hablamos de una o más implementaciones de patrón de diseño observador . Y uno de los objetivos del patrón de diseño del observador es lograr acoplamiento flojo entre objetos.

Eso probablemente no significa mucho sin un buen ejemplo, y ciertamente hay muchos buenos por ahí; Dudo que el mío sea el mejor de ellos, pero igual me daré un buen golpe. Imagina dos objetos. Un objeto quiere saber cuándo sucede algo con el otro objeto, por lo que puede hacer algo por sí mismo; tal vez el perro de la familia, Rover, quiera saludar a papá en la puerta cuando llegue a casa del trabajo. Hay un par de formas en que podría programar ese escenario, ¿verdad?

  • Asegúrese de que papá tenga una referencia a Rover, y cuando llegue a casa, llame al método greetDatAtTheDoor () de Rover, o

  • Dale a Rover una referencia a papá, escuche el evento de Papá en llegar a casa, y cuando se dispara, llama greetDadAtTheDoor () internamente.

En la superficie, puede parecer que no hay mucha diferencia entre los dos, pero en realidad, papá tiene algo de la implementación de Rover grabada en él; Si la implementación de Rover tuviera que cambiar por alguna razón, tendríamos que hacer cambios en dos lugares: una vez en Rover, y luego otra vez en papá. No es un gran problema, tal vez, pero aún así, no es ideal.

Ahora imagina que mamá también quiere saludar a papá. Y el gato, Sr. Bigglesworth, a quien no le gusta mucho papá, quiere asegurarse de que no esté cerca, por lo que prefiere salir. Y un vecino, Joe, quiere saber cuándo llega papá a casa, para poder molestarlo por los veinte dólares que papá le debe. ¿Cómo explicamos todos esos escenarios y los adicionales que inevitablemente surgirán? Colocar referencias al método greetHusband () de mamá, el método getOutNow () del gato, el método greetDadAtTheDoor () del perro y el método goGetMyMoney () de Joe en la definición de clase de papá arruinaría las cosas rápidamente para papá, y sin ninguna buena razón, ya que todo Papá realmente necesita hacer, él mismo, volver a casa. Mamá, el perro, el gato y el vecino solo quieren que se les notifique cuando eso suceda, para que puedan hacer lo que sus implementaciones internas requieran.

Los idiomas manejan los detalles de estas cosas de diferentes maneras, pero como verá cuando comience a buscar en Google, el patrón generalmente implica que haya una matriz, o una estructura similar a una matriz, en el evento '' despachador '' (en este caso, papá, es decir, el objeto en el que todos los demás están interesados) y los suscriptores (p. ej., mamá, el gato, Rover y Joe) todos " registrarse " llamando a un método expuesto públicamente en el despachador y transmitiéndose referencias a sí mismos, referencias que terminan, de alguna forma, en la matriz de "suscriptores" de papá. Luego, cuando papá llega a casa, él '' despacha '' un evento: el "Estoy en casa" evento, digamos, que es esencialmente una función que recorre cada uno de sus suscriptores y los invoca con algún método público accesible propio, solo que es un método cuyo nombre Papá no sabe, no tiene que saber, porque el oyente lo proporcionó cuando lo pasó.

Dado que actualmente codifico principalmente ActionScript, así es como se vería en mi mundo, por ejemplo, según lo declarado desde mi clase de mamá:

var dad:Dad = new Dad();
dad.addEventListener(DadEvent.ARRIVED_HOME, greetHusbandAtDoor);

private function greetHusbandAtDoor(event:DadEvent):void
{
   // Go greet my husband
}

En papá, todo lo que tengo que hacer, cuando llego a casa, es:

dispatchEvent(new DadEvent(DadEvent.ARRIVED_HOME));

... y debido a que Flash maneja los detalles de notificación y envío de eventos para mí (nuevamente, todos lo hacen de manera un poco diferente, pero internamente, Flash sigue el modelo conceptual que describí), mi papá llega a casa, y cada uno miembro de la familia hace

Otros consejos

En un lenguaje compilado, usted escribe su propio bucle de eventos. En un lenguaje de tiempo de ejecución, ya está implementado por el entorno host, y el programador solo obtiene una interfaz abstraída en el sistema de eventos. Nunca ves el bucle de eventos.

Hay dos facetas para crear funcionalidad con eventos. El primero es definir las condiciones bajo las cuales se disparará un evento. En javascript en un navegador, no hay un solo "mousedown" evento. De hecho, hay uno para cada elemento en la página. En este caso, la condición para cuando alguno de ellos se dispare se basa tanto en la ubicación del cursor del mouse como en si el botón del mouse acaba de cambiar del estado hacia arriba al estado hacia abajo. Esta condición puede provocar que se activen múltiples eventos. (En el navegador, hay algo llamado evento '' burbujeo '' que está relacionado con esto. Pero está fuera de alcance aquí).

La otra faceta es el controlador de eventos. Un evento ocurre independientemente de si hay un controlador para él o no. Proporcionar el controlador depende de usted. En javascript, las funciones son valores de primera clase. Se definen en tiempo de ejecución, no en tiempo de compilación, por lo que no hay necesidad de punteros o tablas de salto. Crea una nueva función en tiempo de ejecución y la asigna a una propiedad especial que el entorno host busca cuando se activa un evento en particular.

así que en el desbordamiento de la pila, habrá un controlador de eventos en cada una de las flechas hacia abajo "onclick" eventos, que convierte la flecha roja, disminuye un número, verifica alguna otra variable y muestra una notificación condicionalmente. Luego, cuando el controlador regresa, devuelve el control del subproceso al navegador y, aleluya, el usuario puede interactuar nuevamente con el navegador. (todas las interacciones cesan mientras se maneja un evento, por lo que será mejor que sea rápido). Aquí hay un ejemplo usando la biblioteca jquery.

jQuery("a .downarrow")
.click(function(e){ e.target.style.color="red" /* ... do other things */ });

o en javascript sin procesar (versión 1.6) puede ser

Array.prototype.slice.apply(document.getElementsByTagName("a"))
.filter(function(o){ return !!(/downarrow/).exec(o.className)})
.forEach(function(o){ 
    o.onclick= function(e){ 
        e.target.style.color="red" /* ...do other things * / 
    }
 });

Realmente es así de simple. La razón principal por la que haría algo como esto es que permite la interacción asincrónica. Una aplicación gui no progresa en línea recta, paso a paso. Tiene que responder dinámicamente a la entrada del usuario. Los eventos son una forma de falsificar la apariencia de una aplicación multiproceso. Puede ver al usuario que muchas cosas están sucediendo simultáneamente sin interrumpirse entre sí.

Puede usar una biblioteca para definir un evento personalizado. Esto quizás codificaría algún evento específico de dominio. Por ejemplo: tienes un juego de ajedrez que está pensando en su próximo movimiento. El proceso de búsqueda del movimiento se agota. El juego de ajedrez podría disparar un " onComputerMove " evento. Podrías manejar ese evento con una función que toma las especificaciones del movimiento, actualiza la representación visual del tablero de ajedrez y muestra un mensaje para el usuario y sale. Luego, cuando el jugador se mueve, puedes disparar un " onPlayerMove " evento, que hace casi lo mismo.

Lo más maravilloso de los eventos es que reduce el acoplamiento bidireccional explícito entre dos módulos o clases.

Entonces, digamos que tengo dos clases: Baby and Mommy


Sin eventos, aproximadamente veo dos métodos para permitir que una mamá alimente a un bebé:

  • mamá llama al método baby.pokeBelly () en el Baby cada media hora para saber si tiene que llamar a baby.fillWith (milk) .
    El problema es que el hilo de mamá tiene que esperar todo el día después del bebé en un bucle de tiempo
  • Baby conoce a su mamá asociada y llama a un método mommy.feed (me) , que a su vez llama a baby.fillWith (milk) .
    El problema es que pedirle a un bebé simple que le pida a la mami correcta que se llene la barriga.
    Los bebés no hacen eso, ya que deberían ser simples.

Con eventos, puede vincular un Mommy.OnBabyCries (baby) al evento baby.Cry de su bebé:

void Mommy.OnBabyCries(baby) {
    baby.fillWith(milk)
}

Después de esto, si el bebé quiere comer, todo lo que tiene que hacer es aumentar su evento Cry.

La lógica permanece en la mamá, o incluso más tarde en cualquier niñera, y el bebé se mantiene feliz, sin tener que preocuparse.

No sé si entiendo totalmente tu pregunta, pero una clase con un evento es como una GUI con un botón. Solo piense en ello como un homónimo ... Dentro de cada clase con un evento hay una pequeña persona con un botón virtual para presionar. No sabe qué hará el botón, pero sabe cuándo presionarlo. Ahora piense en una clase relacionada con otra persona pequeña en ella. Esa persona sabe que cuando escucha un mensaje de que se presionó un botón, se supone que debe hacer algo.

Cada vez que quieras que el segundo tipo sepa algo sobre lo que hizo el primero, conectas la centralita entre la primera clase y la segunda clase (Suscríbete al evento). Cuando el primer tipo presiona el botón (dispara el evento), el segundo tipo hace lo que sabe que se supone que debe hacer ...

No sé si esto ayuda o solo estoy en un viaje ácido pensando en pequeñas personas en mis programas ...

En StackOverflow , cuando vota hacia abajo, su reputación cae y su flecha hacia abajo se vuelve roja.

Por lo general, escribe un solo onclick , actualiza todos los elementos que contiene e intenta no olvidar cambiarlo cada vez que cambia el diseño de la página.

En su lugar, puede declarar el evento onVoteDown , activarlo en onclick y suscribirse a este evento:

  • su reputación div
  • su flecha img
  • su XmlHTTPRequest que envía su voto al servidor.

No estoy completamente seguro de qué tipo de respuesta estás buscando, así que te pido disculpas si esto no está cerca. ;)


Por custom , ¿quiere decir acciones personalizadas , disparadores personalizados , o verdaderamente eventos personalizados ?

Por ejemplo: una acción personalizada respondería a un evento predefinido (por ejemplo, un clic del mouse), un disparador personalizado estaría fingiendo un clic del mouse a través de un script, y un evento personalizado sería un oyente que no está definido por el idioma o que no está disponible fácilmente.

Si está buscando eventos personalizados , realmente no puedo ayudarlo. Sin embargo, no creo que haya mucho soporte para ellos en JavaScript.


Para definir una Acción ...

Los eventos normalmente se establecen a través de propiedades predefinidas de un objeto, digamos window.onload . Por defecto, todos son iguales a undefined o null . Por lo tanto, para ponerlos en uso, debe establecerlos en el valor de una función.

Puede usar un " anónimo " función:

window.onload = function (eventObject) {
    /* ... */
};

O configúrelos en una referencia de función (no igual, pero similar a un puntero):

function handleOnload(eventObject) {
    /* ... */
}

window.onload = handleOnload; /* note the lack of parenthesis */

Cuando se activa el evento, se llama a la función. Entonces, en cualquier configuración, cuando la página termine de cargarse, se ejecutará el código que coloque en lugar de / * ... * / .

También hay métodos más formales disponibles para crear eventos. W3C define addEventListener mientras que IE usa attachEvent . Más información .

Hay muchas referencias disponibles para aprender la lista de eventos disponibles. Aquí hay 2 que deberían darle una buena base:


El navegador generalmente maneja la activación de eventos, ya sea para eventos del navegador ( onload ) o eventos de usuario ( onclick ). La propiedad y la función están destinadas a responder.

Activar su propio evento no es lo más fácil de lograr. Definir completamente un objeto Event requiere algo de trabajo, y varía entre los navegadores .

Sin embargo, si no necesita el objeto Event , simplemente puede llamar al evento:

window.onload();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top