Contents

Uma introdução à programação orientada a eventos no Node.js

Principais lições

A programação orientada por eventos é uma abordagem ideal para o desenvolvimento de aplicações interactivas, particularmente aquelas com interfaces gráficas de utilizador (GUIs), uma vez que permite que o código reaja às interacções do utilizador de uma forma imprevisível. Esta flexibilidade acomoda as diversas formas como os utilizadores podem interagir com a aplicação e proporciona uma experiência reactiva que satisfaz as suas necessidades sem problemas.

A programação orientada para eventos tornou-se uma metodologia predominante nas aplicações Web, em que os ouvintes de eventos são activados após a interação do utilizador com o Modelo de Objeto de Documento (DOM).

A incorporação da programação baseada em eventos no Node.js pode ser conseguida sem problemas através da utilização da classe EventEmitter, que facilita a geração de ocorrências personalizadas e a ligação de manipuladores de eventos para a sua gestão adequada.

Ao desenvolver uma aplicação de software, a escolha do paradigma de programação adequado é uma determinação essencial que deve ser feita. O paradigma acaba por influenciar a estrutura e a organização do código, bem como a sua eficiência e facilidade de manutenção. Por conseguinte, é fundamental considerar cuidadosamente qual o paradigma que melhor se alinha com os requisitos e objectivos específicos do projeto antes de se comprometer com uma determinada abordagem.

A programação orientada para eventos, caracterizada pela sua capacidade de resposta a eventos assíncronos que ocorrem numa sequência imprevisível, é particularmente adequada para aplicações que requerem interação com os utilizadores e são normalmente encontradas em interfaces gráficas de utilizador em vez de programas de linha de comandos ou codificação de sistemas incorporados.

O que são eventos?

Um evento pode ser conceptualizado como uma instância de execução iniciada pelo programa ou um estímulo que provoca uma reação do software, que é depois identificada e tratada por um componente funcional designado dentro do código. Tipicamente, um utilizador ou o próprio sistema instigará um evento, levando o código a designar um procedimento específico para processar o resultado.

No domínio da programação informática, uma ocorrência rudimentar seria exemplificada pelo processo de premir uma tecla num teclado para executar uma tarefa específica. Quando esta operação tem lugar, desencadeia uma ocasião conhecida como “evento”, que subsequentemente ativa uma sub-rotina referida como “ouvinte” ou “manipulador”.

O que é a programação orientada para eventos?

A programação orientada para eventos pode ser caracterizada como uma abordagem particular ao desenvolvimento de software, em que a progressão das operações de uma aplicação depende de ocorrências ou eventos específicos, em vez de aderir a uma sequência predeterminada e linear.

Este paradigma específico é normalmente utilizado no desenvolvimento de interfaces de utilizador e aplicações em tempo real, em que a ação de um utilizador serve para iniciar uma resposta correspondente do sistema.

No contexto do desenvolvimento de aplicações Web, a utilização de ouvintes de eventos tornou-se uma abordagem amplamente adoptada, uma vez que são desencadeados em resposta às interacções do utilizador com o Modelo de Objectos de Documento (DOM).

A ilustração supracitada encapsula o mecanismo subjacente à programação orientada por eventos, em que, após a ocorrência de um evento, o canal de eventos correspondente é acionado para transmitir esse evento ao ouvinte designado para processamento.

/pt/images/event_driven_visualization.jpg

Programação orientada por eventos no Node.js

O loop de eventos em JavaScript, que constitui a pedra angular do carácter assíncrono do tempo de execução do Node.js, utiliza a sua arquitetura inerente orientada por eventos, tirando partido do módulo EventEmitter incorporado para garantir uma progressão ininterrupta e eficiente das operações.

Utilizando uma abordagem orientada por eventos, o Node.js permite o desenvolvimento de aplicações baseadas em servidores capazes de acomodar a interatividade do utilizador, operações de entrada/saída e processamento de dados em tempo real, tudo isto sem mecanismos de bloqueio obstrutivos, optimizando assim a eficiência global e proporcionando uma experiência de utilizador sem falhas.

A implementação da programação orientada por eventos no Node.js pode ser um processo simples, uma vez que se tenha uma compreensão abrangente dos fundamentos envolvidos na definição, ativação e gestão de eventos.

A classe EventEmitter

A utilização da classe EventEmitter no Node.js permite a criação de eventos personalizados e o acesso a ouvintes de listas de eventos para manipulá-los. Para integrar a classe no código, importe-a do módulo de eventos por meio da seguinte estrutura:

 // CommonJS
const { EventEmitter } = require("events")

// ES6
import { EventEmitter } from "events" 

Depois que uma instância da classe EventEmitter for criada, ela se tornará acessível dentro do aplicativo para utilização. Isto permite o início de processos de emissão e gestão de eventos.

Por exemplo:

 const FoodEvents = new EventEmitter()

a utilização da metodologia “on”, a adição de um ouvinte através da estratégia “addListener” e a ativação da abordagem “once”.

A utilização da propriedade on constitui a operação fundamental para incorporar manipuladores de eventos, com o método addEventListener() a apresentar uma capacidade idêntica para receber notificações de eventos. Ambos os mecanismos requerem a especificação da ocorrência designada juntamente com uma função à medida que serve de componente reactiva. É possível utilizar estas alternativas sem problemas.

Para utilizar o método “on” para gerir um evento específico, siga estes passos:

 FoodEvents.on("cookie_ready", (data) => {
    console.log("Cookie ready for packaging, data received: ", data);
})

Em vez de utilizar o evento “on” em JavaScript, é possível utilizar o método “addListener” como um substituto imediato.

 FoodEvents.addListener("cookie_ready", (data) => {
    console.log(
        "Cookie will now be packaged and sent out, data received: ",
        data
    );
})

Ambas as instâncias de adição de uma função de retorno de chamada à matriz de ouvintes de eventos para o evento “cookie\_ready” garantem que eles sejam executados sequencialmente quando acionados. A invocação de qualquer uma delas resulta na execução da respectiva função de retorno de chamada.

A implementação desta função envolve o registo de um ouvinte de eventos que é acionado na ocorrência do evento especificado para apenas uma instância. Após a sua execução bem sucedida, o ouvinte de eventos é removido da lista de ouvintes activos para esse evento específico.

Para facilitar uma ocorrência singular, utilize o padrão Singleton em conjunto com o contentor Unity. Esta abordagem garante que apenas uma única instância da classe pretendida é criada e mantida ao longo do tempo de vida da sua aplicação, gerindo eficazmente o âmbito do evento em questão.

 FoodEvents.once("cookie_sent", (data) => {
    console.log("Cookie is sent out, data received: ", data);
})

Neste cenário, o remetente atenderá ao evento cookie\_sent apenas uma vez e erradicará a função de retorno de chamada depois de ter sido executada.

Todas as técnicas acima mencionadas produzem a entidade de origem, permitindo assim invocações consecutivas de qualquer método entre elas.

Lembre-se de que, para que alguém possa processar uma ocorrência, a aplicação correspondente deve libertá-la através da emissão desse evento num determinado momento. A seguir, apresentamos um exemplo que demonstra a emissão do evento cookie\_ready utilizando o método emit:

 function bakeCookie() {
    console.log("Cookie is baking, almost ready...")

    setTimeout(() => {
        FoodEvents.emit("cookie_ready", { flavor: "vanilla cookie" })
    }, 3000)
}

bakeCookie() 

Ao executar o código apresentado, que mostra uma mensagem na consola a indicar que o cookie está a ser preparado, faz uma pausa de três segundos e dispara o evento cookie\_ready, é possível observar uma representação visual semelhante ao gráfico apresentado:

/pt/images/console_output.jpg

O exemplo acima serve para ilustrar a progressão cronológica dos event listeners, que obedece à sequência de registo em que foram alistados.

A classe EventEmitter fornece mais métodos, incluindo:

A função removeListener serve para eliminar uma ocorrência de um ouvinte da coleção de manipuladores de eventos associados a um determinado elemento ou objeto, enquanto a abordagem alternativa, off , fornece uma funcionalidade semelhante.

O método prependListener é utilizado para registar um ouvinte com um emissor de eventos especificado e coloca-o no início da lista de ouvintes para esse evento específico. Ao contrário do método addListener que acrescenta novos ouvintes ao fim de uma fila de ouvintes existente, o método prependListener garante que o ouvinte recém-adicionado será executado antes de todos os outros ouvintes registados anteriormente.

A função prependOnceListener funciona de forma semelhante à prependListener , sendo a principal distinção o facto de o ouvinte especificado ser executado apenas uma vez, análogo ao comportamento exibido pelo método once .

A função removeAllListeners serve para eliminar todos os subscritores associados a uma determinada ocorrência designada, ou todos os ouvintes no caso de não ser fornecido qualquer argumento.

A função listeners devolve um conjunto de todos os ouvintes associados a um evento específico, que é passado como argumento para a função.

O excerto de código fornecido permite obter uma matriz que contém todos os nomes de eventos para os quais foi previamente registado um ouvinte.

No Node.js, é prática comum limitar o número de ouvintes que podem ser registados para um evento, a fim de evitar potenciais fugas de memória. Por defeito, a plataforma lança um aviso se forem adicionados mais de dez ouvintes a um evento. No entanto, esta limitação pode ser ultrapassada através da utilização do método setMaxListeners . Além disso, é possível utilizar a função getMaxListeners para determinar o número máximo de ouvintes permitido para um objeto específico.

O pacote de eventos oferece um conjunto robusto de funcionalidades concebidas para facilitar a programação baseada em eventos no ambiente Node.js.

Quais são algumas práticas recomendadas de programação orientada por eventos?

Ao criar sistemas de software que dependem de eventos, é essencial reconhecer as possíveis desvantagens associadas a cada metodologia. Negligenciar as técnicas ideais pode levar a resultados desfavoráveis para o seu programa. Com isto em mente, aqui estão várias directrizes chave a ter em conta no desenvolvimento de aplicações baseadas em eventos:

Assegure-se de que a nomenclatura dos eventos seja sucinta e informativa, a fim de promover um ambiente de programação bem organizado e de fácil manutenção.

A implementação de técnicas eficazes de tratamento e registo de erros é crucial para facilitar o processo de resolução de problemas que possam surgir durante o desenvolvimento da aplicação.Ao implementar estas práticas recomendadas, os programadores podem identificar e resolver eficazmente quaisquer problemas que ocorram na sua base de código, garantindo assim uma experiência de utilizador mais suave e fiável.

Utilize construções de programação assíncrona, como Promessas e async/await, para atenuar o problema de retornos de chamada aninhados no tratamento de eventos. Esta abordagem oferece uma solução mais elegante do que depender de técnicas de aninhamento incómodas.

É aconselhável evitar estabelecer um número excessivo de ouvintes para um único evento, pois isso pode levar a problemas de desempenho. Em vez disso, considere dividir os eventos e ligá-los em sequência para garantir uma eficiência óptima.

Construir aplicações com a arquitetura certa

Ao construir software, é crucial fazer escolhas de arquitetura e design bem informadas para evitar potenciais armadilhas no futuro. A não adesão a uma estratégia de desenvolvimento sólida pode levar a resultados indesejáveis para a sua aplicação.

A programação orientada por eventos é uma filosofia de design que pode influenciar profundamente a estrutura e a eficiência de uma aplicação. Se o seu programa ou qualquer componente do mesmo depende de eventos para funcionar, então pode valer a pena considerar a programação orientada por eventos como uma abordagem adequada.