Em Node.js muitos dos objetos presentes no ambiente emitem eventos, por exemplo, um servidor TCP emite um evento do tipo conectar toda vez que um novo cliente se conecta ou um fluxo de arquivos emite informações toda vez que uma informação é lida.
Está em Node.js é o que chamamos de emissores de evento, que permitem aos desenvolvedores a possibilidade de inscrever eventos, onde ele inscreve uma função ligue de volta que será invocado sempre que ocorrer um evento no emissor do evento. Podemos até criar nossos próprios emissores de eventos graças à pseudo-classe EventEmitter.
Porém, para entrar com os emissores de eventos, devemos primeiro ter clareza sobre alguns conceitos, como alguns padrões dessas funções, os tipos de eventos e até mesmo os ouvintes.
RequisitosPara realizar os exercícios propostos neste tutorial devemos ter uma instalação funcional de Node.js em nosso sistema, podemos dar uma olhada neste tutorial antes de continuar a nos aprofundar nele. Também é importante poder ter acesso a um editor de rich text para codificar os exemplos, podemos usar o que quisermos, no entanto, para sua facilidade de uso, recomendamos Texto Sublime o NotePad ++ que também tem plugins para a sintaxe JavaScript Y HTML.
Padrão para chamadas de retorno
A programação assíncrona não usa o retorno de valores nas funções para denotar que a função acabou de terminar, mas invoca o famoso callback após a operação ser concluída para que nosso programa possa continuar, onde JavaScript Eu levo a esse tipo de programação, vamos ver um exemplo em Não dê que lê um arquivo e carrega seu conteúdo na memória:
var fs = requer ('fs'); fs.readFile ('file.txt', function (err, fileContent) {if (err) {throw err;} console.log ('Conteúdo do arquivo:', fileContent.toString ());});O que fazemos aqui é enviar uma função anônima como o segundo argumento da função fs.readFile, e como podemos ver que o primeiro argumento da função de retorno de chamada é um objeto de erro, que terá uma instância da classe Error se ocorrer um erro.
Padrão para o emissor do evento
O estilo anterior funciona perfeitamente quando queremos notificar que uma função que estamos executando termina seu trabalho, mas no caso de vários eventos ocorrerem durante esta execução ou muitas vezes, este estilo não funcionará como desejamos. Por exemplo, se quisermos ser avisados toda vez que a informação estiver disponível no socket, uma função do tipo ligue de volta padrão não vai nos ajudar muito, mas é aqui que o emissor do evento pode nos ajudar.
O emissor de evento nada mais é do que um objeto que, como o próprio nome indica, emite um evento, onde um ouvinte é parte do código que se liga a esse emissor e escuta certos tipos de eventos, como:
var req = http.request (options, function (response) {response.on ("data", function (data) {console.log ("Some response data", data);}); response.on ("end" , function () {console.log ("resposta concluída");});}); req.end ();Este é um código puramente explicativo, onde podemos ver algumas das etapas para fazer uma solicitação HTTP para um servidor remoto, mas nos permite ver como o objeto de resposta é um emissor de evento, que pode emitir não apenas dados Y fim mas outros tipos de eventos semelhantes.
Tipos de eventos
De acordo com o exemplo anterior, podemos ver que os eventos emitidos sempre têm um tipo, que é representado por uma string, neste caso "dados"Y"fim”, Que serão strings arbitrárias designadas pelo emissor do evento.
O emissor de evento é uma interface genérica que atende a qualquer tipo de evento, mas há um caso especial na implementação de Não dê e é o evento erro, onde cada evento no ambiente emitirá um evento desse tipo sempre que ocorrer um erro e se o desenvolvedor optar por não ouvir esse tipo de evento e ocorrer um erro, o emissor do evento notará e levantará uma exceção neste caso . Vamos ver no código a seguir como podemos simular esse comportamento:
var em = novo (requer ('eventos'). EventEmitter) (); em.emit ('evento1'); em.emit ('erro', novo Erro ('Meu erro'));Se passarmos pelo console, podemos ver como Não dê nos diz que não estamos tratando do erro, gerando uma exceção não detectada:
Como vimos como os eventos se comportam de maneira geral, vamos ver como usamos a API do emissor de eventos.
Usando a API do emissor de evento
Qualquer objeto que implementa o padrão de emissor de evento implementa uma série de eventos, como podemos ver abaixo:
.addListener - .onEste método nos permite adicionar um ouvinte a um tipo de evento.
.onzeCom esse método, podemos vincular um ouvinte a um tipo de evento, desde que ele seja chamado pelo menos uma vez.
.removeEventListenerEste método nos permitirá remover um ouvinte de qualquer evento.
.removeAllEventListenersPor fim, esse método nos ajuda a remover todos os ouvintes de um determinado tipo de evento.
Já tendo visto qual é a função de cada um deles, vamos ver como os usamos em nossos programas.
Usando .addListener () ou .on () em retornos de chamada
Especificando um tipo de evento e uma função ligue de volta, podemos registrar a ação a ser executada quando um evento específico ocorre. Por exemplo, se quisermos ser informados de que uma parte dos dados está disponível e emitir um evento do tipo data, podemos fazer o seguinte:
função receiveData (data) {console.log ("Os dados foram obtidos:% j", dados); } readFlow.addListener ("dados", receiveData);Também podemos usar o método .em () que é apenas um atalho, vamos ver o equivalente ao código anterior:
função receiveData (data) {console.log ("Os dados foram obtidos:% j", data); } readFlow.on ("dados", receiveData);Podemos até adicionar vários ouvintes para nossos eventos para ouvir o mesmo tipo de evento no mesmo transmissor, por exemplo:
Neste exemplo, o que é feito é associar duas funções ao evento de tipo de dados e, quando o evento de dados é emitido, ambas as strings são impressas. É importante observar que o emissor do evento é responsável por chamar todos ouvintes registrado para um tipo de evento, e ele os chamará na ordem em que foram registrados, o que significa o seguinte:
- Um ouvinte não pode ser chamado imediatamente após o evento ser emitido, é possível que outros ouvintes sejam chamados antes.
- Não capturar exceções é um comportamento prejudicial ao nosso código, portanto, se algum desses ouvintes gerar um erro e não for detectado, é possível que alguns ouvintes não sejam chamados, onde podemos ilustrar isso no exemplo a seguir:
Onde, neste exemplo, o segundo ouvinte não será chamado, pois o primeiro emitiu um erro.
Usando .removeListener ()
Se a qualquer momento não quisermos mais ser informados das alterações em um evento ou objeto específico, podemos interromper a gravação especificando o tipo de evento e a função de retorno de chamada da seguinte forma:
Usando .once ()
No caso de nosso aplicativo estar ouvindo um evento que vai acontecer pelo menos uma vez ou se estivermos interessados em que aconteça apenas uma vez, podemos usar .onze(), que adiciona o ouvinte e o remove assim que ocorre o primeiro evento:
Usando .removeAllListeners ()
Por fim, podemos remover todos os ouvintes de um determinado tipo de evento de um emissor de evento da seguinte maneira:
issuer.removeAllListeners (tipo);
Criação do emissor de evento
O emissor de eventos nos fornece uma maneira genérica de criar interfaces, uma vez que estamos associando eventos em vez de funções, tornando nosso programa mais flexível, mesmo se quisermos usar o padrão de Node.js Em todo o nosso aplicativo, podemos criar uma pseudo classe e herdar de EventEmitter da seguinte forma:
util = requer ('util'); var EventEmitter = require ('eventos'). EventEmitter; var MyClass = function () {} util.inherits (MyClass, EventEmitter);Desta forma, os métodos de EventEmitter Eles estarão disponíveis para nossa instância e podemos usá-los sem problemas e desta forma Minha classe pode emitir eventos:
MyClass.prototype.someMethod = function () {this.emit ("evento personalizado", "argumento 1", "argumento 2"); };Aqui quando algum método é chamado na instância de Minha classe, o exemplo emite um evento chamado evento personalizado, onde por sua vez emite dois dados diferentes, argumento 1 e argumento 2, que serão enviados aos ouvintes de eventos. Finalmente, nas instâncias de Minha classe no lado do cliente, você pode ouvir o evento personalizado da seguinte forma:
var MyClass = new MyClass (); MyClass.on ('evento personalizado', função (str1, str2) {console.log ('Evento personalizado ouvido com argumentos str1% se str2% s!', Str1, str2);});Como podemos ver, o uso de eventos em conjunto com o emissor de eventos nos ajuda a nos comunicarmos com nossa aplicação e foi assim que encerramos este tutorial, onde pudemos ir além da programação assíncrona e aplicar práticas que nos ajudam a manter um padrão e ótimo padrão para nossas aplicações.