Neste artigo vamos utilizar o Node.js com o framework NestJS para demonstrar o uso de eventos, um recurso eficidente de lidar com a comunicação entre diferentes partes de uma aplicação. Vamos criar um exemplo para entender melhor o seu uso.
Curso Nest.js - Fundamentos
Conhecer o cursoCenário
A API receberá os dados do usuário para cadastrar um usuário no cenário do exemplo. Após o cadastro, o usuário receberá dois emails: um e-mail de confirmação do cadastro e outro contendo um link para a criação de uma nova senha.
Configurando o projeto
Primeiramento, caso você não tenha o ambiente Node.js instalado, siga os passos do artigo instalando node.js. Logo em seguida faça a instalação do NestJS CLI, utilizando o seguinte comando:
npm i -g @nestjs/cli
Agora podemos criar um novo projeto utilizando o comando:
nest new evento
Perfeito, a estrutura e os arquivos serão gerados. Para o exemplo, vamos simplesmente criar a interface User, para simular o cadastro de usuário, ao “cadastrar” esse usuário, a aplicação irá utilizar os eventos para disparar os e-mails conforme explicado acima, para isso teremos as seguintes implementações:
- Arquivo referente a interface
User
:
//user.interface.ts
export interface User {
name: string,
email: string
}
Neste caso o usuário terá somente duas propriedades, name e email.
- Arquivo referente ao controller:
//app.controller.ts
import { Body, Controller, Get, Post } from '@nestjs/common';
import { AppService } from './app.service';
import { User } from './user.interface';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) { }
@Post()
createUser(@Body() user: User): User {
return this.appService.createUser(user);
}
}
Utilizamos o controller padrão gerado pelo NestJS, porém alteramos a rota Get para Post, onde vamos receber na requisição um usuário e chamar o método createUser
da camada de serviço, passando o user como parâmetro.
- Arquivo referente a camada service:
//app.service.ts
import { Injectable } from '@nestjs/common';
import { User } from './user.interface';
@Injectable()
export class AppService {
createUser(user: User): User {
//chamada que faz o cadastro no banco.
return user;
}
}
Note que simplesmente retornamos o usuários “cadastrado”. É importante salientar que, em um projeto real, este usuário seria salvo no banco de dados. No entanto, para fins didáticos, vamos nos concentrar agora na utilização dos eventos para o envio dos emails.
Criando o emissor de eventos
Finalmente, podemos configurar o evento que usaremos para o nosso exemplo. O primeiro passo é instalar o pacote event-emitter
para o NestJS e criar o service que usaremos para criar o emissor do evento com os seguintes comandos:
npm i --save @nestjs/event-emitter
Após instalar o event-emitter
, vamos importá-lo no módulo principal da aplicação:
//app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { EventEmitterService } from './events/event-emitter.service';
import { EventEmitterModule } from '@nestjs/event-emitter';
@Module({
imports: [EventEmitterModule.forRoot()],
controllers: [AppController],
providers: [AppService, EventEmitterService],
})
export class AppModule { }
Agora vamos criar o service relacionado aos eventos utilizando o Nest CLI:
nest generate service event-emitter
O Nest irá criar o diretório event-emitter
, para facilitar o exemplo, vamos renomear a pasta para events
e excluir o arquivo de teste que irá gerar dentro deste diretório (o arquivo .spec), em seguida vamos criar o emissor de evento, ou seja, o método que irá emitir o evento e disparar as ações no arquivo event-emitter.service.ts
:
//event-emitter.service.ts
import { Injectable } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { User } from 'src/user.interface';
@Injectable()
export class EventEmitterService {
constructor(private eventEmitter: EventEmitter2) { }
sendNewUserEmails(user: User): void {
this.eventEmitter.emit('user.created', user);
}
}
Veja que utilizamos a injeção de dependências para acessar o eventEmitter
, criamos o método sendNewUserEmails()
, este método irá executar o event.emit()
, desta forma podemos passar como paramêtro a string relacionada ao nome do evento, no caso: user.created
, que passamos como primeiro parâmetro. Outro ponto é que passamos o objeto user
como segundo parâmetro, pois ele será utilizado nos eventos que serão acionados.
Curso Nest.js - Desenvolvimento de APIs REST
Conhecer o cursoCriando um observador de Eventos
Agora precisamos criar os eventos que serão acionados quando o event.emit()
for executado, para isso utilizamos o decorator @OnEvent()
e passamos o evento que foi descrito no event.emit()
que no caso é o evento user.created
.
//event-emitter.service.ts
import { Injectable } from '@nestjs/common';
import { EventEmitter2, OnEvent } from '@nestjs/event-emitter';
import { User } from 'src/user.interface';
@Injectable()
export class EventEmitterService {
constructor(private eventEmitter: EventEmitter2) { }
sendNewUserEmails(user: User): void {
this.eventEmitter.emit('user.created', user);
}
@OnEvent('user.created')
emailNewUser(user: User): void {
console.log(`Envia email para ${user.name} confirmando o cadastro`);
}
@OnEvent('user.created')
newUserPassword(user: User): void {
console.log(`Envia email para ${user.email} com as instruções de criação de senha.`);
}
}
Implementamos dois métodos relacionados a um único evento, ou seja, quando um usuário for cadastrado, a aplicação enviará dois emails, um sobre a confirmação do cadastro e outro para a criação de uma senha. Por último, precisamos chamar o evento de envio dos emails no service
//app.service.ts
import { Injectable } from '@nestjs/common';
import { User } from './user.interface';
import { EventEmitterService } from './events/event-emitter.service';
@Injectable()
export class AppService {
constructor(private event: EventEmitterService) { }
createUser(user: User): User {
//chamada que faz o cadastro no banco.
this.event.sendNewUserEmails(user);
return user;
}
}
Testando
Vamos executar a aplicação com o comando npm run start:dev
e enviar uma requisição para a rota post que foi crianda no controller, contendo os dados de um usuário:
Perfeito, recebemos o retorno 201 created e os dados do usuário “cadastrado”. No exemplo não implementamos o envio propriamente dito dos emails, mas simulamos o envio destes emails com duas mensagens que serão lançadas no console quando o evento for acionado. Ao consultar o terminal, temos o seguinte resultado:
O evento foi disparados com sucesso!
Curso Nest.js - Banco de dados com TypeORM
Conhecer o cursoConclusão
O interessante é que, com essa estrutura onde os eventos são disparados quando um usuário é cadastrado, permite que a nossa aplicação fique mais independente, nós podemos controlar os eventos que serão disparados quando um usuário é cadastrado sem precisar alterar o método createUser()
. Por exemplo, caso no futuro seja necessário implementar uma feature onde o usuário cadastrado deva ser enviado como “lead” para um CRM, nós podemos implementar de forma independente e utilizar o decorator @OnEvent()
observando quando o evento user.created
for chamado sem alterar qualquer outra parte da nossa aplicação relacionda ao cadastro de usuário.
Por fim, caso queira aprender mais sobre NestJS saiba que aqui na TreinaWeb temos o curso Nest.js - Fundamentos que possui 02h07 de vídeos e um total de 18 exercícios. Conheça também nossos outros cursos de TypeScript.
Veja quais são os tópicos abordados durante o curso de Nest.js - Fundamentos:
- Conhecendo a estrutura;
- Utilizando Nest CLI;
- Entendendo Rotas, Controllers e Views;
- Conexão com banco de dados;
- Usando TypeORM;
- Template Engine.