Come funziona un listener di eventi?


125

Durante una delle mie lezioni oggi su Unity, abbiamo discusso dell'aggiornamento della posizione del nostro giocatore controllando ogni frame se l'utente ha premuto un pulsante. Qualcuno ha detto che questo era inefficiente e invece dovremmo usare un listener di eventi.

La mia domanda è, indipendentemente dal linguaggio di programmazione o dalla situazione in cui viene applicata, come funziona un listener di eventi?

La mia intuizione supponeva che l'ascoltatore di eventi controlla costantemente se l'evento è stato generato, il che significa che, nel mio scenario, non sarebbe diverso dal controllare ogni frame se l'evento è stato generato.

Sulla base della discussione in classe, sembra che l'ascoltatore di eventi funzioni in modo diverso.

Come funziona un listener di eventi?


34
Un listener di eventi non controlla affatto. Viene chiamato quando l'evento che sta "ascoltando" gli incendi.
Robert Harvey,

13
Sì, ma come "ascolta", non verificherebbe costantemente?
Gary Holiday

28
No. "Listener di eventi" è probabilmente una cattiva scelta di parole; in realtà non "ascolta" affatto. Tutto ciò che un listener di eventi fa è aspettare di essere chiamato dall'evento quando si attiva, proprio come qualsiasi altro metodo. Fino a quando non viene chiamato in questo modo, non fa nulla.
Robert Harvey,

28
Ogni volta che controlli per vedere se il pulsante è premuto, ti costa cicli di clock. Il gestore eventi (listener) ti costa solo quando il pulsante viene effettivamente premuto.
Robert Harvey,

45
@RobertHarvey - non necessariamente, poiché gli "ascoltatori" hanno ancora bisogno di sondaggi costanti a livello inferiore. Spingi la complessità dal tuo livello di codice in profondità fino agli interrupt di processo o altro. E sì, questo di solito sarà più efficiente, ma non perché l'ascolto è superiore al polling, è perché il polling di livello inferiore è più efficiente del polling da C # e 15 strati di astrazione tra te e l'hardware.
Assapora Ždralo il

Risposte:


140

A differenza dell'esempio di polling fornito (in cui il pulsante è selezionato in ogni frame), un listener di eventi non controlla se il pulsante è stato premuto. Al contrario, viene chiamato quando viene premuto il pulsante.

Forse il termine "ascoltatore di eventi" ti sta gettando. Questo termine suggerisce che "l'ascoltatore" sta attivamente facendo qualcosa per ascoltare, mentre in realtà non sta facendo nulla. L '"ascoltatore" è semplicemente una funzione o un metodo sottoscritto all'evento. Quando l'evento viene generato, viene chiamato il metodo listener ("gestore eventi").

Il vantaggio del modello di evento è che non ci sono costi fino a quando il pulsante non viene effettivamente premuto. L'evento può essere gestito in questo modo senza essere monitorato perché ha origine da ciò che chiamiamo "interrupt hardware", che impedisce brevemente al codice in esecuzione di generare l'evento.

Alcune UI e framework di gioco usano qualcosa chiamato "loop di messaggi", che mette in coda gli eventi per l'esecuzione in un periodo di tempo successivo (in genere breve), ma è comunque necessario un interrupt di processo per inserire l'evento nel loop di messaggi.


54
Vale la pena ricordare che il motivo per cui non vi è alcun costo fino alla pressione del pulsante è perché i pulsanti sono "speciali", il computer ha interruzioni e altre funzioni speciali che il sistema operativo può utilizzare, che sono astratte nelle applicazioni dello spazio utente.
whatsisname

46
@whatsisname mentre questo è il caso molto profondo sotto il cofano, in pratica i motori di gioco probabilmente non funzionano con gli interrupt, ma in realtà stanno ancora eseguendo il polling di una sorgente di eventi in un ciclo. È solo che questo polling è centralizzato e ottimizzato, in modo che l'aggiunta di più listener di eventi non aggiunga polling e complessità aggiuntivi .
gntskn,

7
@PieterGeerkens Immagino che gntskn significasse che come parte del ciclo del motore di gioco, c'è un passaggio che verifica la presenza di eventi eccezionali. Gli eventi verrebbero elaborati durante ogni ciclo insieme a tutte le altre attività una volta per ciclo. Non ci sarebbe un ciclo separato per il controllo degli eventi.
Joshua Taylor,

2
@Voo: motivo in più per non entrare in questo livello di dettaglio in questo post.
Robert Harvey,

2
@Voo: sto parlando di pulsanti come i tasti fisici sulla tastiera e i pulsanti del mouse.
whatsisname

52

Un ascoltatore di eventi simile a un abbonamento alla newsletter via e-mail (ti registri per ricevere gli aggiornamenti, la cui trasmissione viene successivamente avviata dal mittente), piuttosto che aggiornare continuamente una pagina web (dove sei tu a iniziare il trasferimento di informazioni).

Un sistema di eventi viene implementato utilizzando oggetti evento, che gestiscono un elenco di abbonati. Gli oggetti interessati (chiamati abbonati , ascoltatori , delegati , ecc.) Possono iscriversi per essere informati di un evento chiamando un metodo che si iscrive all'evento, facendo sì che l'evento li aggiunga al suo elenco. Ogni volta che l'evento viene licenziato (terminologia può anche includere: chiamata , innescato , invocato , correre , ecc), si chiama il metodo appropriato su ciascuno dei sottoscrittori, per informarli della manifestazione, passando lungo qualunque informazioni contestuali hanno bisogno di capire quello che è successo.


38

La risposta breve e insoddisfacente è che l'applicazione riceve un segnale (l'evento) e che la routine viene chiamata solo a quel punto.

La spiegazione più lunga è un po 'più complicata.

Da dove vengono gli eventi client?

Ogni applicazione moderna ha un "loop" interno, solitamente semi-nascosto, che invia gli eventi ai componenti corretti che dovrebbero riceverli. Ad esempio, un evento "clic" viene inviato al pulsante la cui superficie è visibile alle coordinate correnti del mouse. Questo è al livello più semplice. In realtà il sistema operativo esegue gran parte di questo dispacciamento poiché alcuni eventi e alcuni componenti riceveranno direttamente i messaggi.

Da dove vengono gli eventi dell'applicazione?

I sistemi operativi inviano eventi quando si verificano. Lo fanno in modo reattivo ricevendo una notifica dai propri autisti.

In che modo i conducenti generano eventi?

Non sono un esperto, ma sicuramente alcuni usano interruzioni della CPU: l'hardware che controllano solleva un pin sulla CPU quando sono disponibili nuovi dati; la CPU spegne il driver che gestisce i dati in arrivo che alla fine genera un (coda di) eventi da inviare e quindi restituisce il controllo al sistema operativo.

Quindi, come vedi, la tua applicazione non è davvero in esecuzione per tutto il tempo. Sono un sacco di procedure che vengono attivate dal sistema operativo (sorta) man mano che si verificano eventi, ma non fa nulla per il resto del tempo.


ci sono notevoli eccezioni, ad esempio i giochi per una volta, che potrebbero fare le cose in modo diverso


10
Questa risposta spiega perché non è previsto alcun polling per gli eventi di clic del mouse in un browser. L'hardware genera interrupt => il driver lo risolve in OS event => il browser lo risolve in DOM event => il motore JS esegue il listener per quell'evento.
Tibos,

@Tibos afaict si applica anche agli eventi della tastiera, agli eventi del timer, agli eventi di
disegno

19

Terminologia

  • evento : un tipo di cosa che può accadere.

  • attivazione di eventi : una specifica occorrenza di un evento; un evento sta accadendo.

  • listener di eventi : qualcosa che cerca gli eventi.

  • gestore eventi : qualcosa che si verifica quando un listener di eventi rileva un evento in corso.

  • abbonato all'evento : una risposta che il gestore dell'evento dovrebbe chiamare.

Queste definizioni non dipendono dall'implementazione, quindi possono essere implementate in diversi modi.

Alcuni di questi termini sono comunemente scambiati per sinonimi poiché spesso non è necessario che gli utenti li distinguano.

Scenari comuni

  1. Eventi logici di programmazione.

    • L' evento è quando viene chiamato un metodo.

    • L'attivazione di un evento è una chiamata particolare a quel metodo.

    • Il listener di eventi è un hook nel metodo dell'evento che viene chiamato su ogni attivazione di eventi che chiama il gestore eventi.

    • Il gestore eventi chiama una raccolta di abbonati evento.

    • L' abbonato / gli eventi esegue qualsiasi azione (i) del sistema intende accadere in risposta al verificarsi dell'evento.

  2. Eventi esterni.

    • L' evento è un avvenimento esterno che può essere dedotto da osservabili.

    • L'attivazione di un evento è quando si può riconoscere che si è verificato quell'evento esterno.

    • L' ascoltatore di eventi in qualche modo rileva gli attivamenti degli eventi, spesso eseguendo il polling degli osservabili, quindi chiama il gestore dell'evento quando rileva un innesco dell'evento.

    • Il gestore eventi chiama una raccolta di abbonati evento.

    • L' abbonato / gli eventi esegue qualsiasi azione (i) del sistema intende accadere in risposta al verificarsi dell'evento.

Polling vs. inserimento di ganci nel meccanismo di fuoco dell'evento

Il punto sollevato da altri è che il polling spesso non è necessario. Questo perché i listener di eventi possono essere implementati facendo in modo che gli attivamenti degli eventi chiamino automaticamente il gestore eventi, che è spesso il modo più efficiente di implementare le cose quando gli eventi sono occorrenze a livello di sistema.

Per analogia, non è necessario controllare la posta ogni giorno per la posta se l'operatore postale bussa alla tua porta e ti consegna la posta direttamente a te.

Tuttavia, i listener di eventi possono funzionare anche tramite polling. Il polling non deve necessariamente verificare un valore specifico o altro osservabile; può essere più complesso. Ma, nel complesso, il punto del polling è dedurre quando si è verificato un evento in modo tale da poter rispondere.

Per analogia, devi controllare la tua casella di posta ogni giorno quando l'operatore postale vi lascia la posta. Non dovresti fare questo sondaggio se potessi dare istruzioni al lavoratore postale di bussare alla tua porta, ma spesso non è una possibilità.

Logica degli eventi concatenati

In molti linguaggi di programmazione, è possibile scrivere un evento che viene appena chiamato quando viene premuto un tasto sulla tastiera o in un determinato momento. Sebbene questi siano eventi esterni, non è necessario effettuare il polling per essi. Perché?

È perché il sistema operativo sta eseguendo il polling per te. Ad esempio, Windows controlla cose come i cambiamenti di stato della tastiera e, se ne rileva uno, chiamerà gli abbonati agli eventi. Quindi, quando ti iscrivi a un evento di stampa da tastiera, ti stai effettivamente iscrivendo a un evento che è esso stesso un abbonato a un evento che esegue il polling.

Per analogia, supponiamo che tu stia vivendo in un complesso di appartamenti e che un impiegato delle poste lasci la posta in un'area di ricevimento postale comune. Quindi, un lavoratore simile al sistema operativo può controllare la posta per tutti, consegnando la posta agli appartamenti di coloro che hanno ricevuto qualcosa. Questo risparmia a tutti gli altri il problema di dover effettuare il polling dell'area di ricezione della posta.


La mia intuizione supponeva che l'ascoltatore di eventi controlla costantemente se l'evento è stato generato, il che significa che, nel mio scenario, non sarebbe diverso dal controllare ogni frame se l'evento è stato generato.

Sulla base della discussione in classe, sembra che l'ascoltatore di eventi funzioni in modo diverso.

Come funziona un listener di eventi?

Come sospetti, un evento può funzionare tramite polling. E se un evento è in qualche modo correlato a eventi esterni, ad esempio la pressione di un tasto della tastiera, a un certo punto il polling deve avvenire.

È anche vero che gli eventi non devono necessariamente comportare il polling. Ad esempio, se l'evento è quando viene premuto un pulsante, il listener di eventi di quel pulsante è un metodo che il framework GUI potrebbe chiamare quando determina che un clic del mouse colpisce il pulsante. In questo caso, il polling doveva ancora avvenire per rilevare il clic del mouse, ma l'ascoltatore del mouse è un elemento più passivo collegato al meccanismo di polling primitivo attraverso il concatenamento di eventi.

Aggiornamento: su polling hardware di basso livello

Si scopre che i dispositivi USB e altri protocolli di comunicazione moderni hanno una serie piuttosto affascinante di protocolli di interazione simili a reti, che consentono ai dispositivi I / O di tastiere e mouse di impegnarsi in topologie ad hoc .

È interessante notare che gli " interrupt " sono cose imperative e sincrone, quindi non gestiscono topologie di rete ad hoc . Per risolvere questo problema, gli " interrupt " sono stati generalizzati in pacchetti asincroni ad alta priorità chiamati " transazioni di interrupt " (nel contesto di USB) o " interrupt segnalati da messaggi " (nel contesto di PCI). Questo protocollo è descritto in una specifica USB:

inserisci qui la descrizione dell'immagine

- " Figura 8-31. Bulk / Control / Interrupt OUT Transaction Host State Machine " in "Specifica bus seriale universale, revisione 2.0" , pagina 222 stampata; PDF-page-250 (2000-04-27)

L'essenza sembra essere che i dispositivi I / O e i componenti di comunicazione (come hub USB) agiscano sostanzialmente come dispositivi di rete. Quindi, inviano messaggi, il che richiede il polling delle loro porte e così via. Questo allevia la necessità di linee hardware dedicate.

Sistemi operativi come Windows sembrano gestire la procedura di polling in sé, ad esempio come descritto nella documentazione MSDN per la USB_ENDPOINT_DESCRIPTOR's che descrive come controllare la frequenza di Windows sondaggi un controller host USB per i messaggi di interrupt / isocrono:

Il bIntervalvalore contiene l'intervallo di polling per gli interrupt e gli endpoint isocroni. Per altri tipi di endpoint, questo valore deve essere ignorato. Questo valore riflette la configurazione del dispositivo nel firmware. I driver non possono cambiarlo.

L'intervallo di polling, insieme alla velocità del dispositivo e al tipo di controller host, determinano la frequenza con cui il conducente dovrebbe avviare un interrupt o un trasferimento isocrono. Il valore in bIntervalnon rappresenta un periodo di tempo fisso. È un valore relativo e la frequenza di polling effettiva dipenderà anche dal fatto che il dispositivo e il controller host USB funzionino a bassa, piena o alta velocità.

- "USB_ENDPOINT_DESCRIPTOR struttura" , Hardware Dev Center, Microsoft

I protocolli di connessione del monitor più recenti come DisplayPort sembrano fare lo stesso:

Trasporto multi-stream (MST)

  • MST (Multi-Stream Transport) aggiunto in DisplayPort Ver.1.2

    • Nella versione 1.1a era disponibile solo SST (trasporto a flusso singolo)
  • MST trasporta più flussi A / V su un singolo connettore

    • Fino a 63 flussi; non "Stream per Lane"

      • Nessuna sincronicità assunta tra quei flussi trasportati; uno stream può trovarsi in un periodo di blanking mentre altri no
    • Un trasporto orientato alla connessione

      • Percorso da una sorgente di flusso a un sink di flusso di destinazione stabilito tramite Transazioni messaggi su CH AUX prima dell'inizio di una trasmissione di flusso

      • Aggiunta / eliminazione di un flusso senza influire sui flussi rimanenti

inserisci qui la descrizione dell'immagine

-Slide # 14 da "Panoramica DisplayPortTM Ver.1.2" (06-12-2010)

Questa astrazione consente alcune funzioni pulite, come l'esecuzione di 3 monitor da una connessione:

DisplayPort Multi-Stream Transport consente inoltre di collegare tre o più dispositivi insieme, ma nella configurazione opposta, meno orientata al consumatore: guida simultaneamente più display da una singola porta di uscita.

- "DisplayPort" , Wikipedia

Concettualmente, il punto da togliere a questo è che i meccanismi di polling consentono comunicazioni seriali più generalizzate, il che è fantastico quando si desidera funzionalità più generali. Quindi, l'hardware e il sistema operativo eseguono molti polling per il sistema logico. Quindi, i consumatori che si iscrivono agli eventi possono godere di quei dettagli gestiti per loro dal sistema di livello inferiore, senza dover scrivere i propri protocolli di polling / passaggio messaggi.

Alla fine, eventi come la pressione dei tasti sembrano passare attraverso una serie piuttosto interessante di eventi prima di arrivare al meccanismo imperativo di attivazione del livello software.


Per quanto riguarda il tuo ultimo paragrafo, in genere non viene eseguito alcun polling a basso livello, il sistema operativo reagisce agli interrupt di processo che vengono attivati ​​dai dispositivi periferici. Un computer in genere ha molti dispositivi collegati (mouse, tastiera, unità disco, schede di rete) e il polling di tutti sarebbe molto inefficiente.
Barmar

Tuttavia, le tue analogie con la consegna della posta sono esattamente come spiegherei l'attività di livello superiore.
Barmar

1
@Barmar Ya, quando i dispositivi si sono spostati su connessioni USB, si è parlato molto di come sono passati dalla generazione diretta di interruzioni (come fa una tastiera PS / 2) alla richiesta di polling (come una tastiera USB), e alcune fonti affermano che il polling viene eseguito dalla CPU. Ma altre fonti affermano che è fatto su un controller specializzato che converte il polling in un interrupt per la CPU.
Nat

@Barmar Vuoi sapere quale è corretto? Probabilmente ho visto più fonti affermare che la CPU esegue il polling che altrimenti, ma un controller specializzato sembra avere più senso. Voglio dire, penso che Arduino e altri dispositivi embedded tendano a richiedere alla CPU di eseguire il polling, ma non so dei dispositivi di tipo x86.
Nat

1
Se qualcuno può confermare in modo da poter aggiornare questa risposta, penso che i moderni dispositivi I / O, ad esempio quelli collegati tramite USB, scrivano direttamente nella memoria , bypassando il controllo della CPU (motivo per cui sono veloci / efficienti e una sicurezza pericolo a volte ). Quindi, è necessario un sistema operativo moderno per eseguire il polling della memoria per verificare la presenza di nuovi messaggi.
Nat

8

Pull vs Push

Esistono due strategie principali per verificare se si è verificato un evento o viene raggiunto uno stato specifico. Ad esempio, immagina di aspettare una consegna importante:

  • Pull : ogni 10 minuti, scendi nella tua casella di posta e controlla se è stato consegnato,
  • Push : dì al fattorino di chiamarti quando eseguono la consegna.

L' approccio pull (chiamato anche polling) è più semplice: è possibile implementarlo senza alcuna funzione speciale. D'altra parte, è spesso meno efficiente poiché si rischia di fare controlli extra senza nulla da mostrare per loro.

D'altra parte, l' approccio push è generalmente più efficiente: il tuo codice viene eseguito solo quando ha qualcosa da fare. D'altra parte, richiede l'esistenza di un meccanismo per la registrazione di un ascoltatore / osservatore / callback 1 .

1 Il mio postino in genere manca di un tale meccanismo, purtroppo.


1

Riguardo all'unità nello specifico - non c'è altro modo di controllare l'input del giocatore se non quello di interrogarlo ogni fotogramma. Per creare un listener di eventi, avresti comunque bisogno di un oggetto come "sistema eventi" o "gestore eventi" per eseguire il polling, quindi spingerebbe il problema a una classe diversa.

Concesso, una volta che hai un gestore di eventi, hai una sola classe che esegue il polling dell'input per ogni frame, ma questo non offre alcun evidente vantaggio in termini di prestazioni, poiché ora questa classe deve iterare sugli ascoltatori e chiamarli, che, a seconda del tuo gioco design (come in, quanti ascoltatori ci sono e con quale frequenza il player utilizza input), potrebbe effettivamente essere più costoso.

Oltre a tutto ciò, ricorda la regola d'oro: l'ottimizzazione prematura è la radice di tutto il male , il che è particolarmente vero nei videogiochi, dove spesso il processo di rendering di ogni fotogramma costa così tanto, che piccole ottimizzazioni di script come questo sono completamente insignificanti


Non vedrei un ciclo di eventi centrale come ottimizzazione ma come scrittura di codice più leggibile e comprensibile in opposizione al polling diffuso in tutta la base di codice. Permette anche eventi "sintetici" ed eventi che non provengono dal polling del motore di gioco.
BlackJack,

@BlackJack Sono d'accordo e di solito lo codice da solo in questo modo, ma l'OP ha chiesto delle prestazioni. A proposito, Unity ha sorprendentemente molte decisioni discutibili sulla progettazione di codici come questo, come avere funzioni statiche quasi ovunque.
Non so

1

A meno che tu non abbia un supporto nel tuo sistema operativo / framework che gestisca eventi come la pressione dei pulsanti o l'overflow del timer o l'arrivo dei messaggi, dovrai implementare questo scalpello del listener di eventi usando comunque il polling (da qualche parte sotto).

Ma non allontanarti da questo modello di progettazione solo perché non hai subito un vantaggio in termini di prestazioni. Ecco i motivi per cui dovresti usarlo indipendentemente dal fatto che tu abbia o meno supporto alla gestione degli eventi.

  1. Il codice sembra più pulito e più isolato (se implementato correttamente, ovviamente)
  2. Il codice basato sui gestori di eventi sopporta meglio le modifiche (poiché normalmente si modificano solo alcuni dei gestori di eventi)
  3. Se ti capita di passare alla piattaforma con supporto per gli eventi di base, puoi riutilizzare i gestori di eventi esistenti e sbarazzarti del codice di polling.

Conclusione: sei stato fortunato a partecipare alla discussione e hai imparato un'alternativa al sondaggio. Cerca un'opportunità per applicare questo concetto in pratica e apprezzerai quanto sia elegante il codice.


1

La maggior parte dei loop di eventi sono costruiti sopra alcune primitive di polling multiplex fornite dal sistema operativo. Su Linux, quella primitiva è spesso la poll(2) chiamata di sistema (ma potrebbe essere quella precedente select). Nelle applicazioni GUI, il server di visualizzazione (ad esempio Xorg o Wayland ) sta comunicando (tramite un socket (7) o pipe (7) ) con l'applicazione. Leggi anche i protocolli e l'architettura del sistema X Window .

Tali primitive di polling sono efficienti; il kernel in pratica riattiva il processo quando viene fatto un input (e viene gestito un certo interrupt).

In concreto, la libreria del tuo toolkit widget comunica con il tuo server di visualizzazione, in attesa di messaggi e invia questi messaggi ai tuoi widget. Le librerie di toolkit come Qt o GTK sono piuttosto complesse (milioni di righe di codice sorgente). La tastiera e il mouse sono gestiti solo dal processo del server di visualizzazione (che traduce tali input in messaggi di evento inviati alle applicazioni client).

(Sto semplificando; in effetti le cose sono molto più complesse)


1

In un sistema basato esclusivamente sul polling, il sottosistema che potrebbe voler sapere quando si verifica una determinata azione dovrà eseguire un codice ogni volta che l'azione potrebbe verificarsi. Se ci sono molti sottosistemi che dovrebbero reagire ciascuno entro 10 ms da un evento non necessariamente unico, tutti dovrebbero verificare almeno 100 volte / secondo se si è verificato il loro evento. Se tali sottosistemi si trovano in processi thread (o peggio, processi) diversi, ciò richiederebbe il passaggio in ogni thread o processo 100x / secondo.

Se molte delle cose che le applicazioni cercheranno sono piuttosto simili, potrebbe essere più efficiente avere un sottosistema di monitoraggio centralizzato - forse guidato da una tabella - che può guardare molte cose e osservare se una di esse è cambiata. Se ci sono 32 switch, ad esempio, una piattaforma potrebbe avere una funzione per leggere tutti i 32 switch contemporaneamente in una parola, rendendo possibile per il codice del monitor verificare se sono stati cambiati switch tra i sondaggi e, in caso contrario, no preoccuparsi di quale codice potrebbe essere interessato a loro.

Se ci sono molti sottosistemi che vorrebbero ricevere una notifica quando qualcosa cambia, avere un sottosistema di monitoraggio dedicato notifica ad altri sottosistemi quando si verificano eventi a cui sono interessati potrebbe essere più efficiente che avere ciascun sottosistema polling dei propri eventi. La creazione di un sottosistema di monitoraggio dedicato nei casi in cui nessuno sia interessato a eventi, tuttavia, rappresenterebbe un puro spreco di risorse. Se ci sono solo alcuni sottosistemi che sono interessati agli eventi, il costo per farli guardare agli eventi a cui sono interessati potrebbe essere inferiore al costo di creazione di un sottosistema di monitoraggio dedicato per scopi generici, ma il pareggio il punto varierà in modo significativo tra piattaforme diverse.


0

Un ascoltatore di eventi è come un orecchio in attesa di un messaggio. Quando si verifica l'evento, la subroutine scelta come listener di eventi funziona utilizzando gli argomenti dell'evento.

Esistono sempre due dati importanti: il momento in cui si verifica l'evento e l'oggetto in cui si verifica questo evento. Altro argomento sono ulteriori dati su ciò che è accaduto.

Il listener di eventi specifica la reazione a ciò che si verifica.


0

Un listener di eventi segue il modello Pubblica / Sottoscrivi (come abbonato)

Nella sua forma più semplice, un oggetto di pubblicazione mantiene un elenco di istruzioni degli abbonati da eseguire quando è necessario pubblicare qualcosa.

Avrà un qualche tipo di subscribe(x)metodo, in cui x dipende da come il gestore eventi è progettato per gestire l'evento. Quando viene chiamato iscriviti (x), x viene aggiunto all'elenco degli editori delle istruzioni / riferimenti degli abbonati.

L'editore può contenere tutta, parte o nessuna della logica per la gestione dell'evento. Potrebbe semplicemente richiedere riferimenti agli abbonati per notificarli / trasformarli con la logica specificata quando si verifica l'evento. Potrebbe non contenere alcuna logica e richiedere oggetti del sottoscrittore (metodi / listener di eventi) in grado di gestire l'evento. È molto probabile che contenga una miscela di entrambi.

Quando si verifica un evento, l'editore ripeterà ed eseguirà la sua logica per ciascun elemento nel suo elenco di istruzioni / riferimenti degli abbonati.

Non importa quanto sia complesso un gestore di eventi, al suo interno segue questo semplice schema.

Esempi

Per un esempio di listener di eventi, si fornisce un metodo / funzione / istruzione / listener di eventi al metodo iscriviti () del gestore eventi. Il gestore eventi aggiunge il metodo al suo elenco di callback degli abbonati. Quando si verifica un evento, il gestore eventi scorre il proprio elenco ed esegue ciascun callback.

Per un esempio reale, quando ti iscrivi alla newsletter su Stack Exchange, un riferimento al tuo profilo verrà aggiunto a una tabella del database degli abbonati. Quando è il momento di pubblicare la newsletter, il riferimento verrà utilizzato per popolare un modello della newsletter e verrà inviato alla tua e-mail. In questo caso, x è semplicemente un riferimento a te e l'editore ha una serie di istruzioni interne utilizzate per tutti gli abbonati.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.