domingo, 24 de abril de 2016

EventEmitters em Node.js

Em Node.js a classe EventEmitter é responsável por emitir eventos, e também, por adicionar listeners para esses eventos. Os listeners são callbacks que são chamados toda vez que o evento em questão ocorre. Para cada evento podemos ter um ou mais listeners.

Exemplo:

var http = require('http');

var server = http.createServer( (req, res) => {

 // req e res são streams e em Node.js todas as streams são EventEmitters

 // se não setarmos o encoding para utf-8 vamos receber objetos da classe Buffer ao invés de strings
  req.setEncoding('utf8');
  
  // adicionamos um listener para o evento data que recebe como argumento 
  // os dados enviados na requisição
  req.on('data', (data) => {
    // escrevemos os dados recebidos de volta como resposta
    res.write(data+'\n');
  });
  
  // adicionamos um listener para o evento end
  req.on('end', () => {    
    // chamamos o método end() de respose
    res.end();
  });

});

// Iniciamos o servido escutando na porta 3000
server.listen(3000);

Para testar, abra um terminal e digite:
curl http://localhost:3000 -d {} // {}
curl http://localhost:3000 -d '"string'" // string
curl http://localhost:3000 -d 10 // 10

No exemplo acima utilizamos o módulo http para criar um servidor escutando na porta 3000. O método createServer de http recebe como calback uma função com os argumentos req (request) e res (response). Utilizando o EventEmitter req nós registramos event listeners para os eventos data e end.

Todos os eventos tem um tipo que é definido por uma string, como no exemplo acima, "data" e "end". A única forma de saber os tipos de eventos disponíveis em determinada API é através de sua documentação, não é possível descobrir estes tipos programaticamente. No entanto, grande parte dos event emitters do Node.js emitem o evento "error". Fica a cargo do programador registrar um listener para este evento ou não. Se não houver um listener para tratar o evento error, e este ocorrer, o event emitter lançará uma exceção não tratada.

É possível também criarmos nossos próprios EventEmitters como no exemplo a seguir:

// criamos um objeto do tipo EventEmitter chamado meuEmitter
// a classe EventEmitter encontra-se no módulo 'events'
var meuEmitter = new (require('events')).EventEmitter();

// Todo EventEmitter emite o evento 'newListener' quando um listener é adicionado
// utilizamos once para que seja chamado somente uma vez, para não ocorrer um loop infinito
meuEmitter.once('newListener', (evento, listener) => {
if(evento === 'evento') {
// o evento newListener será acionado antes que um listener seja adicionado ao array interno de listeners
// desta forma o listener adicionado dentro de 'newListener' será adicionado antes de qualquer outro
meuEmitter.on('evento', () => {
console.log("chamado primeiro");
});
}
});

function listener() {
console.log("chamado depois");
}

// registramos um listener para o evento "evento" que não recebe nenhum argumento
meuEmitter.on('evento', listener);

// registramos um listener para o evento "evento2" que recebe um argumento
// "on" e "addListener" fazem exatamente a mesma coisa
meuEmitter.addListener('evento2', (num) => {
console.log(num*num);
});

// o método emit emite o evento
meuEmitter.emit('evento');
// chamado primeiro
// chamado depois

meuEmitter.emit('evento2', 5);
// 25

// o método removeListener remove um listener de determinado evento
meuEmitter.removeListener('evento', listener);
meuEmitter.emit('evento');
// chamado primeiro

Espero que este post tenha sido útil.
Abraço.


Nenhum comentário:

Postar um comentário