freeCodeCamp/guide/portuguese/nodejs/event-emitters/index.md

8.4 KiB
Raw Blame History

title localeTitle
Event Emitters Emissores de Eventos

Eventos e Transmissões

Tradicionalmente, em um servidor da Web, processar um dado na forma de um arquivo lendo e gravando consome muito mais memória, pois esses métodos de processamento precisam carregar o arquivo toda vez que ele precisar ler ou gravar esse arquivo. Isso é considerado um desperdício de recursos. Pense nisso, em termos de escalabilidade e Big Data, se estamos desperdiçando recursos, vamos nos comprometer muito. A natureza assíncrona do Node.js fornece duas opções adequadas para trabalharmos e fornecer um fluxo de dados que consome menos recursos, pois o Node.js é baseado em um modelo assíncrono sem bloqueio. Eles estão emitindo eventos e fluxos. Nesta seção, vamos dar uma olhada em ambos.

Classe EventEmitter

EventEmitters são uma das principais idéias por trás da arquitetura de programação orientada a eventos ou programação assíncrona em Node.js. Um EventEmitter é um objeto e, no Node.js, qualquer objeto que emite um evento é uma instância da classe EventEmitter. O que é um evento? Todas as ações executadas pelo programa Node.js, como iniciar o servidor da Web e fechar o encerramento do programa quando não há solicitações a serem atendidas, são consideradas como dois eventos separados.

Para acessar a classe EventEmitter em um programa Node.js, você precisa exigir o módulo de events da API Node.js. Para criar o objeto, criamos uma instância da classe EventEmitter chamando sua função construtora.

const events = require('events'); 
 
 const eventEmitter = new events.EventEmitter(); 

Ou você pode exigir acesso direto à subclasse EventEmitter da seguinte forma:

const EventEmitter = require('events'); 
 
 const eventEmitter = new EventEmitter(); 

Uma classe EventEmitter fornece vários métodos predefinidos para trabalhar com eventos. Estes métodos são .on , .emit e .error . Emitir um evento de uma função pode ser feito acionando uma função de retorno de chamada que pode ser acessada por qualquer outra função JavaScript. Isso é como transmitir.

A capacidade de acionar um evento pode ser feita seguindo a sintaxe:

eventEmitter.emit(eventName, optionalData); 

E a capacidade de anexar uma função de ouvinte e definir o nome de um evento específico é feita por .on .

eventEmitter.emit(eventName, callback); 

Vamos imitar as novas funções que acabamos de aprender com um exemplo. Crie um novo arquivo chamado eventemitter.js e cole o seguinte código:

const EventEmitter = require('events'); 
 
 const eventEmitter = new EventEmitter(); 
 
 const callback = () => { 
    console.log('callback runs'); 
 }; 
 
 eventEmitter.on('invoke', callback); 
 
 eventEmitter.emit('invoke'); 
 eventEmitter.emit('invoke'); 

Agora execute o exemplo acima usando o comando node e você deve obter a seguinte saída.

callback runs 
 callback runs 

Começamos criando uma instância eventEmitter através do qual tenha acesso aos .on o método. O .on método adiciona o evento, definindo o nome invoke que usamos mais tarde na .emit chamar acionar a função de retorno de chamada associado a ele.

Há outra função que a classe EventEmitter fornece, chamada .once . Esse método invoca apenas a função de retorno de chamada associada a um evento pela primeira vez quando um evento é emitido. Considere o exemplo abaixo.

const EventEmitter = require('events'); 
 
 const eventEmitter = new EventEmitter(); 
 
 const callback = () => { 
    console.log('callback runs'); 
 }; 
 
 eventEmitter.once('invoke', callback); 
 
 eventEmitter.emit('invoke'); 
 eventEmitter.emit('invoke'); 

Saída

callback runs 

.once manter as faixas de eventos de quando elas são acionadas e quantas vezes elas são acionadas, ao contrário do método .on , que não acompanha essa situação. Esta é uma diferença importante entre os dois.

Compreender fluxos

O Node.js fornece outra maneira de trabalhar com dados, em vez de consumir uma grande quantidade de recursos de memória e torná-lo econômico. Isso que fluxos fazem. Basicamente, os fluxos permitem que você leia dados da única fonte e os coloque no destino. Os fluxos processam os dados em blocos em vez de todos de uma só vez, tornando-os adequados para trabalhar com grandes conjuntos de dados. Muitos módulos Node.js internos usam streams sob o capô. Por exemplo, solicitação e resposta HTTP, sockets TCP, zlib, crypto, fs lêem e gravam fluxos, etc.

Tipo de fluxos

No Node.js, existem quatro tipos de fluxos:

  • Legível
  • Gravável
  • Duplex
  • Transformar

Os mais comuns são fluxos legíveis e graváveis. Os fluxos legíveis são usados para ler os dados da origem e os fluxos graváveis são usados para executar a operação de gravação desses dados no destino. Fluxos duplex podem ser usados para executar operações de leitura e gravação. Transform é um superconjunto de fluxos Duplex, com a única diferença é que os dados podem ser modificados durante a leitura ou gravação.

Tipo de eventos de fluxo

Todos esses tipos de fluxo são instâncias da classe EventEmitter, o que significa que eles emitem eventos de leitura e gravação. Cada tipo de fluxo pode emitir os seguintes eventos.

  • data: esse evento é acionado quando os dados estão disponíveis para leitura pelo fluxo legível
  • error: Este evento é acionado quando há um erro ao ler ou gravar os dados
  • end: este evento é acionado quando não há dados para ler

Correntes legíveis

Um fluxo legível permite ler os dados da fonte. Esta fonte pode ser qualquer coisa, desde um buffer, um arquivo, etc. Primeiro, crie um arquivo de texto simples a partir do qual vamos ler os dados usando o fluxo.

I am Text file that contains data. 

Agora, crie um novo arquivo chamado read.js, que implementará a funcionalidade de leitura de dados desse arquivo de texto usando um fluxo legível.

const fs = require('fs'); 
 const readableStream = fs.createReadStream('abc.txt'); 
 let data = ''; 
 
 readableStream.on('data', function(chunk) { 
    data += chunk; 
 }); 
 
 readableStream.on('end', function() { 
    console.log(data); 
 }); 

Se você executar o programa acima, você receberá a seguinte saída:

 $ node test.js 
 I am Text file that contains data. 

Qual é o que escrevemos dentro do arquivo de texto. Para ler dados usando o fluxo, usamos uma função chamada createReadStream() do módulo do sistema de arquivos fs .

Quando não há dados para ler pelo fluxo legível, ele automaticamente termina a função de retorno de chamada. O método .on é o que aprendemos na seção anterior da classe EventEmitter. Isso significa que os streams usam a classe EventEmitter nos bastidores.

Stream gravável

Os fluxos graváveis são usados para gravar ou inserir ou anexar dados a um destino. Como fluxos legíveis, eles também são fornecidos pelo módulo fs . Crie um novo arquivo chamado wrtte.js no qual usará um fluxo legível para ler dados da origem e gravá-lo em um destino criando um novo arquivo .txt .

const fs = require('fs'); 
 const readableStream = fs.createReadStream('./abc.txt'); 
 const writeableStream = fs.createWriteStream('./dest.txt'); 
 let data = ''; 
 
 readableStream.on('data', function(chunk) { 
    writeableStream.write(chunk); 
 }); 

Quando você executa este programa, um novo arquivo será criado pelo fluxo gravável desde que tenha acesso ao módulo do sistema de arquivos. O fluxo gravável usa o método .write() para produzir os dados no destino. No exemplo acima, estamos criando um novo arquivo chamado dest.txt que conterá os mesmos dados de abc.txt .

Tubulação

Piping é um mecanismo pelo qual você pode ler dados a partir da fonte e escrevê-lo para o destino sem escrever muito código como fizemos acima e não usar .on ou .write métodos.

Se estamos a escrever acima exemplo usando pipe, vamos escrever como abaixo:

const fs = require('fs'); 
 const readableStream = fs.createReadStream('./abc.txt'); 
 const writeableStream = fs.createWriteStream('./dest.txt'); 
 
 readableStream.pipe(writeableStream); 

Observe quantas linhas de código foram removidas. Além disso, agora precisamos apenas dos caminhos de arquivos de origem e de destino e, para ler e gravar dados, estamos usando o método .pipe() .