Desenvolvimento Back-end Node

Trabalhando com eventos no NestJS

Neste artigo vamos aprender a utilizar os eventos com o NestJS, criando um exemplo onde vamos simular o envio de e-mails.

há 2 meses 3 semanas

Formação Desenvolvedor Node Full-Stack
Conheça a formação em detalhes

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.

Nest.js - Fundamentos
Curso Nest.js - Fundamentos
Conhecer o curso

Cená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 createUserda 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.

Nest.js -  Desenvolvimento de APIs REST
Curso Nest.js - Desenvolvimento de APIs REST
Conhecer o curso

Criando 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:

cadastrando usuário para disparar os eventos

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:

simulando envio de emails

O evento foi disparados com sucesso!

Nest.js  - Banco de dados com TypeORM
Curso Nest.js - Banco de dados com TypeORM
Conhecer o curso

Conclusã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.

Autor(a) do artigo

Wesley Gado
Wesley Gado

Formado em Análise e Desenvolvimento de Sistemas pelo Instituto Federal de São Paulo, atuou em projetos como desenvolvedor Front-End. Nas horas vagas grava Podcast e arrisca uns três acordes no violão.

Todos os artigos

Artigos relacionados Ver todos