Como um ouvinte de eventos funciona?

125

Durante uma das minhas palestras de hoje sobre o Unity, discutimos a atualização da posição do jogador, verificando cada quadro se o usuário tiver um botão pressionado. Alguém disse que isso era ineficiente e que deveríamos usar um ouvinte de evento.

Minha pergunta é: independentemente da linguagem de programação ou da situação em que é aplicada, como funciona um ouvinte de eventos?

Minha intuição presumiria que o ouvinte de eventos verifica constantemente se o evento foi disparado, o que significa que, no meu cenário, não seria diferente de verificar todos os quadros se o evento foi disparado.

Com base na discussão em sala de aula, parece que o ouvinte de eventos funciona de uma maneira diferente.

Como um ouvinte de eventos funciona?

Gary Holiday
fonte
34
Um ouvinte de evento não verifica nada. É chamado quando o evento que está "ouvindo" é acionado.
Robert Harvey
13
Sim, mas como "escuta", não seria verificado constantemente?
Gary férias
28
Não. "Event Listener" é provavelmente uma má escolha de palavras; na verdade, não "escuta". Tudo o que um ouvinte de evento faz é esperar para ser chamado pelo evento quando ele for disparado, como qualquer outro método. Até ser chamado dessa maneira, não faz nada.
Robert Harvey
28
Toda vez que você verifica se o botão é pressionado, custa um relógio. O manipulador de eventos (ouvinte) custa apenas quando o botão é realmente pressionado.
Robert Harvey
45
@RobertHarvey - não necessariamente, pois os "ouvintes" ainda precisam de pesquisas constantes no nível inferior. Você apenas expande a complexidade de sua própria camada de código para interrupções de hardware ou qualquer outra coisa. E sim, isso geralmente será mais eficiente, mas não porque a escuta seja superior à pesquisa, é porque a pesquisa em nível inferior é mais eficiente do que a pesquisa em C # e 15 camadas de abstração entre você e o hardware.
Davor Ždralo 4/01/18

Respostas:

140

Diferente do exemplo de pesquisa que você forneceu (onde o botão é verificado em todos os quadros), um ouvinte de evento não verifica se o botão foi pressionado. Em vez disso, é chamado quando o botão é pressionado.

Talvez o termo "ouvinte de eventos" esteja jogando você. Esse termo sugere que o "ouvinte" está ativamente fazendo algo para ouvir, quando na verdade não está fazendo nada. O "ouvinte" é apenas uma função ou método que está inscrito no evento. Quando o evento é acionado, o método listener ("manipulador de eventos") é chamado.

O benefício do padrão de evento é que não há custo até que o botão seja realmente pressionado. O evento pode ser tratado dessa maneira sem ser monitorado porque se origina do que chamamos de "interrupção de hardware", que antecipa brevemente o código em execução para disparar o evento.

Algumas estruturas de interface do usuário e de jogos usam algo chamado "loop de mensagem", que enfileira eventos para execução em algum período posterior (geralmente curto), mas você ainda precisa de uma interrupção de hardware para inserir esse evento no loop de mensagens.

Robert Harvey
fonte
54
Vale a pena mencionar a razão pela qual não há custo até que o botão seja pressionado, porque os botões são "especiais", o computador tem interrupções e outras instalações especiais que o sistema operacional pode usar, abstraídas nos aplicativos do espaço do usuário.
Whatsisname
46
@whatsisname, embora esse seja o caso muito profundo , na prática, os mecanismos de jogo provavelmente não estão funcionando com interrupções, mas na verdade ainda estão pesquisando uma fonte de eventos em um loop. É apenas que essa pesquisa é centralizada e otimizada, para que a adição de mais ouvintes de eventos não adicione pesquisa e complexidade adicionais .
Gntskn
7
@PieterGeerkens Eu acho que o gntskn significa que, como parte do ciclo do mecanismo de jogo, há uma etapa que verifica se há eventos pendentes. Os eventos seriam processados ​​durante cada loop, juntamente com todas as outras atividades uma vez por loop. Não haveria um loop separado para verificar eventos.
21418 Joshua Taylor
2
@Voo: Mais uma razão para não entrar nesse nível de detalhe neste post.
Robert Harvey
2
@Voo: Estou falando de botões como as teclas físicas no teclado e nos botões do mouse.
Whatsisname
52

Um ouvinte de evento semelhante a uma assinatura de boletim informativo por email (você se registra para receber atualizações, cuja transmissão é iniciada posteriormente pelo remetente), em vez de atualizar continuamente uma página da Web (onde você está iniciando a transferência de informações).

Um sistema de eventos é implementado usando objetos de eventos, que gerenciam uma lista de assinantes. Objetos interessados ​​(chamados assinantes , ouvintes , delegados etc.) podem se inscrever para serem informados de um evento chamando um método que se inscreve no evento, o que faz com que o evento os adicione à sua lista. Sempre que o evento é acionado (a terminologia também pode incluir: chamado , acionado , invocado , executado etc.), ele chama o método apropriado em cada um dos assinantes, para informá-los do evento, transmitindo as informações contextuais que eles precisam entender o que aconteceu.

Alexander
fonte
38

A resposta curta e insatisfatória é que o aplicativo recebe um sinal (o evento) e que a rotina é chamada apenas nesse ponto.

A explicação mais longa é um pouco mais envolvida.

De onde vêm os eventos do cliente?

Cada aplicativo moderno possui um "loop de eventos" interno, geralmente semi-oculto, que envia eventos para os componentes corretos que devem recebê-los. Por exemplo, um evento "clique" é enviado ao botão cuja superfície é visível nas coordenadas atuais do mouse. Isso está no nível mais simples. Na realidade, o sistema operacional faz muito esse envio, pois alguns eventos e alguns componentes receberão mensagens diretamente.

De onde vêm os eventos do aplicativo?

Os sistemas operacionais despacham eventos conforme eles acontecem. Eles fazem isso reativamente sendo notificados por seus próprios motoristas.

Como os drivers geram eventos?

Eu não sou especialista, mas com certeza alguns usam interrupções na CPU: o hardware que eles controlam gera um alfinete na CPU quando novos dados estão disponíveis; a CPU dispara o driver que lida com os dados recebidos, o que eventualmente gera uma (fila de) eventos a serem despachados e, em seguida, retorna o controle de volta ao sistema operacional.

Então, como você vê, seu aplicativo não está sendo executado o tempo todo. É um monte de procedimentos que são disparados pelo sistema operacional (sorta) à medida que os eventos acontecem, mas não fazem nada o resto do tempo.


existem exceções notáveis, como jogos pela primeira vez, que podem fazer coisas de maneira diferente

Sklivvz
fonte
10
Esta resposta explica por que não há pesquisas envolvidas nos eventos de clique do mouse em um navegador. O hardware gera interrupção => o driver resolve para o evento do SO => o navegador resolve para o evento DOM => o mecanismo JS executa o ouvinte para esse evento.
Tibos 04/01
@ Tibos afirma que também se aplica a eventos de teclado, eventos de timer, eventos de pintura etc.
Sklivvz
19

Terminologia

  • evento : um tipo de coisa que pode acontecer.

  • disparo de evento : uma ocorrência específica de um evento; um evento acontecendo.

  • ouvinte de evento : algo que atenta para acionamentos de eventos.

  • manipulador de eventos : algo que ocorre quando um ouvinte de eventos detecta um disparo de evento.

  • assinante de evento : uma resposta que o manipulador de eventos deveria chamar.

Essas definições não dependem da implementação, portanto podem ser implementadas de maneiras diferentes.

Alguns desses termos geralmente são confundidos com sinônimos, pois muitas vezes não é necessário que os usuários façam distinção entre eles.

Cenários comuns

  1. Eventos de lógica de programação.

    • O evento é quando algum método é chamado.

    • Um disparo de evento é uma chamada específica para esse método.

    • O ouvinte de evento é um gancho no método de evento chamado em cada disparo de evento que chama o manipulador de eventos.

    • O manipulador de eventos chama uma coleção de assinantes de eventos.

    • O (s) assinante (s) do evento executam todas as ações que o sistema pretende que aconteçam em resposta à ocorrência do evento.

  2. Eventos externos.

    • O evento é um acontecimento externo que pode ser inferido a partir de observáveis.

    • Um disparo de evento é quando esse acontecimento externo pode ser reconhecido como tendo ocorrido.

    • O ouvinte de eventos de alguma forma detecta disparos de eventos, geralmente pesquisando os observáveis, e então chama o manipulador de eventos ao detectar um disparo de evento.

    • O manipulador de eventos chama uma coleção de assinantes de eventos.

    • O (s) assinante (s) do evento executam todas as ações que o sistema pretende que aconteçam em resposta à ocorrência do evento.

Pesquisa versus inserção de ganchos no mecanismo de disparo do evento

O argumento de outras pessoas é que as pesquisas geralmente não são necessárias. Isso ocorre porque os ouvintes de eventos podem ser implementados fazendo com que os acionamentos de eventos chamem automaticamente o manipulador de eventos, que geralmente é a maneira mais eficiente de implementar coisas quando os eventos são ocorrências no nível do sistema.

Por analogia, você não precisa verificar a caixa de correio todos os dias se o funcionário bater à sua porta e entregar a correspondência diretamente a você.

No entanto, os ouvintes de eventos também podem trabalhar pesquisando. A pesquisa não precisa necessariamente verificar um valor específico ou outro observável; pode ser mais complexo. Mas, em geral, o objetivo da pesquisa é inferir quando algum evento ocorreu, para que possa ser respondido.

Por analogia, você deve verificar sua caixa de correio todos os dias quando o funcionário dos correios simplesmente solta a correspondência nela. Você não precisaria fazer esse trabalho de votação se pudesse instruir o funcionário a bater à sua porta, mas isso geralmente não é uma possibilidade.

Encadeando a lógica do evento

Em muitas linguagens de programação, você pode escrever um evento chamado apenas quando uma tecla do teclado é pressionada ou em um determinado momento. Embora sejam eventos externos, você não precisa fazer uma pesquisa para eles. Por quê?

É porque o sistema operacional está pesquisando para você. Por exemplo, o Windows verifica itens como alterações de estado do teclado e, se detectar um, chama os assinantes do evento. Portanto, quando você se inscreve em um evento de pressionamento de teclado, na verdade está se inscrevendo em um evento que é ele próprio um assinante de um evento que é pesquisado.

Por analogia, diga que você está morando em um complexo de apartamentos e um funcionário dos correios envia as cartas para uma área de recebimento de correspondência. Em seguida, um trabalhador do tipo sistema operacional pode verificar se há correio para todos, entregando correio nos apartamentos daqueles que receberam algo. Isso poupa a todos os demais de ter que pesquisar a área de recebimento de correio.


Minha intuição presumiria que o ouvinte de eventos verifica constantemente se o evento foi disparado, o que significa que, no meu cenário, não seria diferente de verificar todos os quadros se o evento foi disparado.

Com base na discussão em sala de aula, parece que o ouvinte de eventos funciona de uma maneira diferente.

Como um ouvinte de eventos funciona?

Como você suspeitou, um evento pode funcionar através de pesquisas. E se um evento está de alguma forma relacionado a acontecimentos externos, por exemplo, uma tecla do teclado sendo pressionada, a pesquisa precisa acontecer em algum momento.

Também é verdade que os eventos não precisam necessariamente envolver pesquisas. Por exemplo, se o evento é quando um botão é pressionado, o ouvinte de evento desse botão é um método que a estrutura da GUI pode chamar quando determina que um clique do mouse bate no botão. Nesse caso, ainda era necessário realizar a pesquisa para que o clique do mouse fosse detectado, mas o ouvinte do mouse é um elemento mais passivo conectado ao mecanismo de pesquisa primitiva por meio do encadeamento de eventos.

Atualização: na pesquisa de hardware de baixo nível

Acontece que os dispositivos USB e outros protocolos de comunicação modernos têm um conjunto de protocolos bastante fascinante para interações, permitindo que dispositivos de E / S, incluindo teclados e mouses, se envolvam em topologias ad hoc .

Curiosamente, as " interrupções " são coisas bastante imperativas e síncronas, para que não lidem com topologias de rede ad hoc . Para corrigir isso, " interrupções " foram generalizadas em pacotes assíncronos de alta prioridade chamados " transações de interrupção " (no contexto do USB) ou " interrupções sinalizadas por mensagem " (no contexto do PCI). Este protocolo é descrito em uma especificação USB:

insira a descrição da imagem aqui

- " Figura 8-31. Máquina de estado de host de transação OUT de volume / controle / interrupção " em "Especificação de barramento serial universal, revisão 2.0" , página impressa-222; Página-PDF-250 (27-04-200 2000)

A essência parece ser que dispositivos de E / S e componentes de comunicação (como hubs USB) agem basicamente como dispositivos de rede. Então, eles enviam mensagens, o que requer a pesquisa de suas portas e tal. Isso alivia a necessidade de linhas de hardware dedicadas.

Sistemas operacionais como Windows parecem lidar com o próprio processo de votação, por exemplo, como descrito na documentação do MSDN para o USB_ENDPOINT_DESCRIPTOR's que descreve como controlar a frequência do Windows urnas um controlador de host USB para mensagens de interrupção / isócronos:

O bIntervalvalor contém o intervalo de pesquisa para pontos finais de interrupção e isócrono. Para outros tipos de terminal, esse valor deve ser ignorado. Este valor reflete a configuração do dispositivo no firmware. Os drivers não podem mudar isso.

O intervalo de pesquisa, juntamente com a velocidade do dispositivo e o tipo de controlador host, determinam a frequência com a qual o driver deve iniciar uma interrupção ou uma transferência isócrona. O valor em bIntervalnão representa um período fixo de tempo. É um valor relativo, e a frequência real de pesquisa também dependerá se o dispositivo e o controlador host USB operam em velocidade baixa, máxima ou alta.

- "Estrutura USB_ENDPOINT_DESCRIPTOR" , Centro de Desenvolvimento de Hardware, Microsoft

Protocolos de conexão de monitor mais recentes, como o DisplayPort, parecem fazer o mesmo:

Transporte Multi-Stream (MST)

  • MST (Transporte Multi-Stream) adicionado no DisplayPort Ver.1.2

    • Somente SST (transporte de fluxo único) estava disponível na versão 1.1a
  • O MST transporta vários fluxos A / V por um único conector

    • Até 63 fluxos; não "Stream per Lane"

      • Nenhuma sincronicidade assumida entre os fluxos transportados; um fluxo pode estar em um período de supressão, enquanto outros não
    • Um transporte orientado a conexão

      • Caminho de uma fonte de fluxo para um coletor de fluxo de destino estabelecido por meio de Transações de mensagens nos AUX CH 's antes do início de uma transmissão de fluxo

      • Adição / exclusão de um fluxo sem afetar os fluxos restantes

insira a descrição da imagem aqui

-Slide # 14 de "DisplayPortTM Ver.1.2 Overview" (2010-12-06)

Essa abstração permite alguns recursos interessantes, como a execução de 3 monitores em uma conexão:

O DisplayPort Multi-Stream Transport também permite conectar três ou mais dispositivos juntos, mas, ao contrário, configuração menos orientada ao "consumidor": direciona simultaneamente vários monitores a partir de uma única porta de saída.

- "DisplayPort" , Wikipedia

Conceitualmente, o ponto a se afastar disso é que os mecanismos de pesquisa permitem comunicações seriais mais generalizadas, o que é incrível quando você deseja uma funcionalidade mais geral. Portanto, o hardware e o SO fazem muitas pesquisas para o sistema lógico. Em seguida, os consumidores que se inscrevem em eventos podem aproveitar esses detalhes sendo tratados pelo sistema de nível inferior, sem precisar escrever seus próprios protocolos de pesquisa / transmissão de mensagens.

Por fim, eventos como pressionamentos de teclas parecem passar por uma série bastante interessante de eventos antes de chegar ao mecanismo imperativo de acionamento de eventos do nível de software.

Nat
fonte
Em relação ao seu último parágrafo, geralmente não há pesquisas realizadas no nível baixo, o sistema operacional reage às interrupções de hardware que são acionadas por dispositivos periféricos. Um computador normalmente possui muitos dispositivos conectados (mouse, teclado, unidades de disco, placas de rede) e a sondagem de todos eles seria muito ineficiente.
Barmar
No entanto, suas analogias com a entrega de correio são exatamente como eu explicaria a atividade de nível superior.
Barmar
1
@ Barmar Ya sabe, quando os dispositivos mudaram para conexões USB, houve muita conversa sobre como eles passaram de gerar interrupções diretamente (como um teclado PS / 2) para exigir pesquisas (como um teclado USB) e algumas fontes afirmam que a pesquisa é feita pela CPU. Porém, outras fontes afirmam que isso é feito em um controlador especializado que converte a pesquisa em uma interrupção para a CPU.
Nat
@ Barmar Você saberia o que é correto? Eu provavelmente já vi mais fontes afirmarem que a CPU faz a pesquisa do que o contrário, mas um controlador especializado para isso parece fazer mais sentido. Quero dizer, acho que o Arduino e outros dispositivos incorporados tendem a exigir que a CPU faça a pesquisa, mas não sei quanto a dispositivos do tipo x86.
Nat
1
Se alguém puder confirmar para que eu possa atualizar esta resposta, acho que os dispositivos de E / S modernos, por exemplo, aqueles conectados por USB, gravam diretamente na memória , ignorando o controle da CPU (e é por isso que eles são rápidos / eficientes e uma segurança perigo às vezes ). Em seguida, é necessário um sistema operacional moderno para pesquisar a memória e procurar novas mensagens.
Nat
8

Pull vs Push

Existem duas estratégias principais para verificar se um evento ocorreu ou se um estado específico é atingido. Por exemplo, imagine aguardar uma entrega importante:

  • Pull : a cada 10 minutos, vá até sua caixa de correio e verifique se ela foi entregue,
  • Push : diga ao entregador para ligar quando você fizer a entrega.

A abordagem pull (também chamada de polling) é mais simples: você pode implementá-la sem nenhum recurso especial. Por outro lado, geralmente é menos eficiente, pois você corre o risco de fazer verificações extras sem nada para mostrar.

Por outro lado, a abordagem push é geralmente mais eficiente: seu código é executado apenas quando há algo a fazer. Por outro lado, requer que exista um mecanismo para você registrar um ouvinte / observador / retorno de chamada 1 .

1 Meu carteiro normalmente não possui esse mecanismo, infelizmente.

Matthieu M.
fonte
1

Sobre a unidade em específico - não há outra maneira de verificar a entrada do jogador além de pesquisar todos os quadros. Para criar um ouvinte de evento, você ainda precisaria de um objeto como "sistema de eventos" ou "gerenciador de eventos" para fazer a pesquisa, para que apenas levasse o problema a uma classe diferente.

É verdade que, depois de ter um gerente de eventos, você tem apenas uma classe pesquisando a entrada em cada quadro, mas isso não oferece vantagens óbvias de desempenho, já que agora essa classe precisa interagir com os ouvintes e chamá-los, que, dependendo do seu jogo design (por exemplo, quantos ouvintes existem e com que frequência o player utiliza entrada) pode ser realmente mais caro.

Além de tudo isso, lembre-se da regra de ouro - a otimização prematura é a raiz de todo mal , o que é especialmente verdadeiro nos videogames, onde geralmente o processo de renderização de cada quadro custa tanto, que pequenas otimizações de script como essa são completamente insignificantes

Não sei
fonte
Eu não veria um loop central de eventos como otimização, mas como escrever código mais legível e compreensível, em oposição a pesquisas espalhadas por toda a base de código. Ele também permite eventos "sintéticos" e eventos não provenientes da pesquisa no mecanismo do jogo.
precisa
@BlackJack Eu concordo e geralmente codifico dessa maneira, mas o OP perguntou sobre desempenho. Aliás, o Unity tem surpreendentemente muitas decisões dúbias de design de código como essa, como ter funções estáticas em quase todos os lugares.
Dunno
1

A menos que você tenha algum suporte no OS / Framework que lide com eventos como pressionar o botão ou estourar o timer ou a chegada de mensagens - você precisará implementar esse padrão do Event Listener usando a pesquisa de qualquer maneira (em algum lugar abaixo).

Mas não se afaste desse padrão de design apenas porque você não tem um benefício de desempenho imediatamente. Aqui estão as razões pelas quais você deve usá-lo, independentemente de ter suporte subjacente para manipulação de eventos ou não.

  1. O código parece mais limpo e mais isolado (se implementado corretamente, é claro)
  2. O código baseado nos manipuladores de eventos melhor suporta alterações (já que você normalmente modifica apenas alguns dos manipuladores de eventos)
  3. Se você mudar para a plataforma com suporte a eventos subjacentes - poderá reutilizar seus manipuladores de eventos existentes e se livrar do código de pesquisa.

Conclusão - você teve a sorte de participar da discussão e aprendeu uma alternativa à votação. Procure uma oportunidade para aplicar esse conceito na prática e você apreciará o quão elegante o código pode ser.

OpalApps
fonte
1

A maioria dos loops de eventos é criada acima de uma primitiva de multiplexação de sondagem fornecida pelo sistema operacional. No Linux, essa primitiva geralmente é a chamada do sistema poll(2) (mas pode ser a antiga select). Nos aplicativos GUI, o servidor de exibição (por exemplo , Xorg ou Wayland ) está se comunicando (através de um soquete (7) ou tubo (7) ) com seu aplicativo. Leia também sobre os protocolos e a arquitetura do sistema X Window .

Tais primitivas de votação são eficientes; na prática, o kernel ativaria seu processo quando alguma entrada fosse feita (e alguma interrupção fosse tratada).

Concretamente, a biblioteca do kit de ferramentas do widget se comunica com o servidor de exibição, aguardando mensagens e enviando essas mensagens para os widgets. Bibliotecas de kits de ferramentas como Qt ou GTK são bastante complexas (milhões de linhas de código fonte). Seu teclado e mouse são tratados apenas pelo processo do servidor de exibição (que converte essas entradas em mensagens de eventos enviadas para aplicativos clientes).

(Estou simplificando; de fato, as coisas são muito mais complexas)

Basile Starynkevitch
fonte
1

Em um sistema puramente baseado em pesquisas, o subsistema que talvez queira saber quando alguma ação específica ocorre precisará executar algum código sempre que essa ação ocorrer. Se houver muitos subsistemas que precisariam reagir dentro de 10 ms após a ocorrência de algum evento não necessariamente único, todos precisariam verificar pelo menos 100 vezes / segundo se o evento havia ocorrido. Se esses subsistemas estiverem em processos diferentes de encadeamentos (ou pior, processos), isso exigiria a troca de cada encadeamento ou processo 100x / segundo.

Se muitas das coisas que os aplicativos observam são bastante semelhantes, pode ser mais eficiente ter um subsistema de monitoramento centralizado - talvez orientado por tabelas - que possa observar muitas coisas e observar se alguma delas foi alterada. Se houver 32 comutadores, por exemplo, uma plataforma poderá ter uma função para ler todos os 32 comutadores de uma só vez em uma palavra, possibilitando ao código do monitor verificar se algum comutador foi alterado entre pesquisas e - se não - não se preocupe com o código que pode estar interessado neles.

Se houver muitos subsistemas que desejam notificação quando algo mudar, ter um subsistema de monitoramento dedicado notificar outros subsistemas quando ocorrerem eventos nos quais eles estão interessados ​​pode ser mais eficiente do que cada subsistema pesquisar seus próprios eventos. A configuração de um subsistema de monitoramento dedicado nos casos em que ninguém está interessado em nenhum evento, no entanto, representaria um puro desperdício de recursos. Se houver apenas alguns subsistemas interessados ​​em eventos, o custo de vê-los assistir aos eventos nos quais eles estão interessados ​​pode ser menor do que o custo de configurar um subsistema de monitoramento dedicado de uso geral, mas o ponto de equilíbrio O ponto varia significativamente entre as diferentes plataformas.

supercat
fonte
0

Um ouvinte de evento é como um ouvido aguardando uma mensagem. Quando o evento ocorre, a sub-rotina escolhida como ouvinte de eventos funciona usando os argumentos do evento.

Sempre existem dois dados importantes: o momento em que o evento acontece e o objeto em que esse evento ocorre. Outro argumento são mais dados sobre o que aconteceu.

O ouvinte de evento especifica a reação àquela que ocorre.

Rafael Marazuela
fonte
0

Um Ouvinte de Evento segue o Padrão de Publicação / Assinatura (como assinante)

Na sua forma mais simples, um objeto de publicação mantém uma lista de instruções dos assinantes a serem executadas quando algo precisar ser publicado.

Ele terá algum tipo de subscribe(x)método, em que x depende de como o manipulador de eventos foi projetado para lidar com o evento. Quando a inscrição (x) é chamada, x é adicionado à lista de editores das instruções / referências dos assinantes.

O editor pode conter toda, parte ou nenhuma lógica para manipular o evento. Pode simplesmente exigir referências aos assinantes para notificá-los / transformá-los com sua lógica especificada quando o evento ocorrer. Pode não conter lógica e exigir objetos de assinante (métodos / ouvintes de eventos) que possam manipular o evento. É mais provável que contenha uma mistura de ambos.

Quando um evento ocorre, o editor itera e executa sua lógica para cada item da lista de instruções / referências dos assinantes.

Não importa a complexidade de um manipulador de eventos, ele segue esse padrão simples.

Exemplos

Para um exemplo de ouvinte de evento, você fornece um método / função / instrução / ouvinte de evento ao método subscribe () do manipulador de eventos. O manipulador de eventos adiciona o método à sua lista de retornos de chamada de assinante. Quando um evento ocorre, o manipulador de eventos itera sobre sua lista e executa cada retorno de chamada.

Para um exemplo do mundo real, quando você assina o boletim no Stack Exchange, uma referência ao seu perfil será adicionada a uma tabela de assinantes do banco de dados. Quando chegar a hora de publicar o boletim, a referência será usada para preencher um modelo do boletim e será enviada para seu email. Nesse caso, x é simplesmente uma referência a você, e o editor possui um conjunto de instruções internas usadas para todos os assinantes.

Dom
fonte