Event Bus e padrão Observer em JavaScript (Node.js): implementação e exemplos

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Event Bus e padrão Observer em JavaScript (Node.js)



No desenvolvimento moderno com Node.js, surge frequentemente a necessidade de organizar uma interação fracamente acoplada entre os componentes da aplicação. Para resolver esse problema, o padrão Observer e sua implementação prática — Event Bus (Barramento de Eventos) — são ideais. Neste artigo, vamos detalhar o que é Event Bus, como ele se relaciona com o padrão Observer e criar nossa própria implementação em JavaScript puro para Node.js.



O que é o padrão Observer?



O padrão Observer define uma relação "um para muitos" entre objetos. Quando um objeto (sujeito ou editor) altera seu estado, todos os objetos dependentes dele (observadores ou assinantes) são automaticamente notificados. No Node.js, esse padrão está integrado ao núcleo através da classe EventEmitter.



Componentes principais do padrão:

  • Subject (Sujeito) — objeto que gera eventos.
  • Observer (Observador) — objeto que se inscreve nos eventos.
  • Subscription (Inscrição) — mecanismo de registro do observador no sujeito.


O que é Event Bus?



Event Bus é um mediador centralizado que implementa o padrão Observer. Em vez de cada componente se inscrever diretamente em outro componente, todos se comunicam através de um único barramento de eventos. Isso oferece as seguintes vantagens:

  • Baixo acoplamento dos componentes.
  • Facilidade para adicionar novos assinantes sem alterar o código do editor.
  • Possibilidade de gerenciamento centralizado de eventos (logging, filtragem, depuração).


EventEmitter nativo no Node.js



O Node.js fornece o módulo nativo events, que contém a classe EventEmitter. Esta é uma implementação pronta de Event Bus. Vamos ver um exemplo básico:



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

// Inscrevendo-se no evento 'user:login'eventBus.on('user:login', (user) => { console.log(`Usuário ${user.name} fez login`);});

// Inscrevendo-se com outro manipuladoreventBus.on('user:login', (user) => { console.log(`Enviando e-mail de boas-vindas para ${user.email}`);});

// Gerando o eventoeventBus.emit('user:login', { name: 'Ivan', email: 'ivan@example.com' });// Saída:// Usuário Ivan fez login// Enviando e-mail de boas-vindas para ivan@example.com


Criando seu próprio Event Bus



Às vezes, o EventEmitter nativo não é suficiente — por exemplo, se for necessário adicionar suporte a manipuladores assíncronos, prioridades ou tipagem estrita. Vamos criar nossa própria implementação de Event Bus do zero:



class EventBus {    constructor() {        this.events = {};    }

// Inscrição em um evento on(eventName, callback) { if (!this.events[eventName]) { this.events[eventName] = []; } this.events[eventName].push(callback); // Retorna uma função para cancelar a inscrição return () => { this.events[eventName] = this.events[eventName] .filter(cb => cb !== callback); }; }

// Inscrição em evento único once(eventName, callback) { const wrapper = (...args) => { callback(...args); this.off(eventName, wrapper); }; this.on(eventName, wrapper); }

// Geração de evento emit(eventName, ...args) { const callbacks = this.events[eventName]; if (!callbacks) return false; callbacks.forEach(callback => { try { callback(...args); } catch (error) { console.error(`Erro no manipulador do evento ${eventName}:`, error); } }); return true;

Recommendations