DEV Community

Cover image for Introdução ao Node.js (Single-Thread, Event-Loop e mercado)
Fábio J L Ferreira
Fábio J L Ferreira

Posted on

Introdução ao Node.js (Single-Thread, Event-Loop e mercado)

Este capítulo não tem por finalidade contar a história do Node.js, afinal de contas o site oficial e o guia de inicio rápido fazem isso muito bem. Serei prático e objetivo ao abordar somente os conceitos essenciais, logo indispensáveis a qualquer “desenvolvedor aventureiro”.


Livro

Este conteúdo representa um texto de amostra (primeira versão ainda em desenvolvimento) do Livro Node.js para iniciantes. Para acompanhar o desenvolvimento, acesse: https://github.com/fabiojaniolima/livros#livros


O que é Node.js

No guia oficial de começo rápido (Quick Start), temos basicamente a seguinte introdução:

O Node.js é um ambiente de tempo de execução JavaScript de código aberto e multiplataforma. É uma ferramenta popular para quase qualquer tipo de projeto!

O Node.js executa o motor JavaScript V8, o núcleo do Google Chrome, fora do navegador. Isso permite que o Node.js seja muito eficiente.

Para maiores detalhes a respeito, bem como para conhecer a história da plataforma, acesse: https://nodejs.dev/introduction-to-nodejs

Em outras palavras, o Node.js é um runtime JavaScript server-side, ou seja, uma solução que possibilita ao desenvolvedor executar aplicações escritas em JavaScript do lado do servidor, de forma simples, rápida e performática. Isso é possível basicamente graças ao motor V8 e a biblioteca libuv — solução open-source para a qual dedicaremos mais algumas linhas logo adiante.

O JavaScript é considerado uma linguagem interpretado, porém, internamente o Node.js, mais precisamente o motor V8 realiza a compilação do código utilizando just-in-time (JIT) afim de acelerar o processo de execução do código.

Uma sugestão de amigo

Antes de continuarmos, é muito importante que você tenha conhecimento dos links abaixo e gaste ao menos alguns minutos apreciando o que eles tem a oferecer:

Funcionamento básico

Muitos iniciantes enfrentam dificuldades ao tentar compreender o ciclo de vida dos eventos no Node.js. Pode parecer complexo à primeira vista, mas as aparências enganam. A compreensão deste processo se torna mais acessível ao focarmos em dois conceitos fundamentais: Single-Thread e Event-Loop.

Single-Thread

Node.js é uma plataforma orientada a eventos que opera sob o princípio de uma única thread, gerenciando eficientemente a pilha de eventos ou Call Stack. Esta pilha adota a estratégia LIFO (Last In, First Out), onde a última entrada é a primeira a ser processada. As operações de fundo, ou background, são administradas por ‘workers’ que operam em segundo plano, e estes podem executar tarefas multi-thread.

Os "workers" são, essencialmente, processos de I/O assíncronos e não-bloqueantes, gerenciados pela libuv. Esta é uma biblioteca open-source, multiplataforma, escrita em C, que se vale de um pool de threads para gerir operações paralelas. A abordagem de thread única na gestão da Call Stack é vital para o alto desempenho do Node.js.

🔗 Para uma exploração mais aprofundada deste conceito, sugiro consultar: The Node.js Event Loop, Timers, and process.nextTick()

Event-Loop

Ao tratar do Event-Loop, evitarei detalhar aspectos mais complexos e momentaneamente desnecessários, como Micro Task Queue, Next Tick Queue, Timers Queue, Immediates Queue, entre outros. Em vez disso, vamos nos concentrar no que de fato é relevante neste momento.

O Event-Loop é responsável por monitorar a Call Stack e processar eventos. Quando um evento é detectado e não representa uma operação extensa, ele é executado imediatamente. Operações mais longas, como leituras em disco ou comunicações de rede, são despachadas para um “worker” em um thread separado. Isso libera o Event-Loop para continuar processando outros eventos na pilha. Uma vez concluída a operação em segundo plano, sua função de callback é enfileirada e aguarda a liberação do Event-Loop para ser executada.

Este modelo permite que o Node.js lide eficientemente com I/O assíncrono, evitando bloqueios e mantendo a aplicação responsiva.

A seguir, apresento uma representação simplificada do Event-Loop e seu funcionamento, focando em transmitir a essência desse mecanismo de forma acessível:

Representação simples e abstrata do Event-Loop.

Talvez eu seja um pouco repetitivo agora, porém, vamos analisar a imagem acima aproveitando para revisar o que foi apresentado previamente:

No Node.js, os eventos são empilhados na Stack. O Event-Loop monitora essa Stack, identificando e processando eventos. Para eventos que não requerem operações extensas, a execução é imediata, permitindo que o Event-Loop passe rapidamente para o próximo evento.

Entretanto, eventos que envolvem “operações longas” — como leitura de arquivos ou comunicação de rede — são abordados de maneira diferente. Nesses casos, o Event-Loop delega a tarefa, junto com sua função de callback, ao Background Thread. Aqui, a libuv entra em cena, gerenciando a operação em um thread separado. Isso permite que o Event-Loop continue processando outros eventos na Stack sem interrupções.

Uma vez concluída a operação pelo Background Thread, a função de callback é colocada na Task Queue. O Event-Loop, que opera em uma única thread, só processará esta callback após finalizar as tarefas correntes na Stack. Esta abordagem assegura um gerenciamento eficiente de múltiplas tarefas pelo Event-Loop, alternando entre execuções rápidas de operações breves e o manejo de operações mais demoradas em segundo plano.

Esta estrutura é vital para a eficiência do Node.js, habilitando-o a lidar com um volume elevado de operações de I/O de forma não-bloqueante e assíncrona.

Veja um exemplo prático de funcionamento:

Representação simples e abstrata do Event-Loop e seu funcionamento.

No exemplo ilustrado, temos dois eventos na Stack. O primeiro a ser processado é o fs.readFile(), seguindo o princípio LIFO (Last In, First Out) da Stack. Sendo fs.readFile() uma operação de I/O em disco — portanto, uma operação mais lenta e potencialmente bloqueante — ela é delegada para execução em background pela libuv.

Quando esta tarefa de leitura de arquivo é concluída, seu callback é colocado na Task Queue. Este callback aguardará sua vez para ser transferido para a Stack. E quando acontecerá essa transferência? Acontecerá quando a Stack estiver vazia. Nesse momento, o callback é movido da Task Queue para a Stack e, finalmente, processado pelo Event-Loop.

Caso tenha interesse em aprofundar no assunto, acesse: https://dev.to/khaosdoctor/node-js-por-baixo-dos-panos-3-um-mergulho-no-event-loop-38l9 e https://imasters.com.br/front-end/node-js-o-que-e-esse-event-loop-afinal

Vantagens da plataforma

  • Gerenciador de pacotes nativo (NPM): Instalando o Node.js, você obtém o NPM, um poderoso gerenciador de pacotes, facilitando o início do desenvolvimento.
  • JavaScript em Todo Lugar: Com o Node.js, o JavaScript, anteriormente limitado a funções de front-end, expande seu alcance para o back-end, mobile e desktop, dinamizando o desenvolvimento e a manutenção.
  • Comunidade Ativa e Integrada: A união das comunidades de Node.js e JavaScript promove uma sinergia poderosa, apoiando desde tarefas de desenvolvimento front-end até automações complexas.
  • Eficiência e Leveza: O modelo de Event-Loop do Node.js garante uma performance excepcional, otimizando o uso de RAM e CPU e evitando a sobrecarga por processos múltiplos. I/O Não-Bloqueante: O Node.js lida com operações de I/O de forma assíncrona e não-bloqueante, mantendo a fluidez do fluxo de trabalho.
  • Ecossistema Rico: Com um vasto repositório de bibliotecas e módulos disponíveis no NPM, o Node.js atende a uma ampla gama de necessidades de desenvolvimento. Multiplataforma: Funcionando em diversas plataformas como Windows, macOS e Linux, o Node.js oferece grande versatilidade.
  • Ideal para Aplicações em Tempo Real: Seu modelo assíncrono torna o Node.js perfeito para aplicações que exigem processamento em tempo real, como chats e jogos online.

Quem está utilizando?

O Node.js é amplamente adotado por uma variedade de usuários, desde indivíduos até grandes corporações, incluindo empresas renomadas como:

  • Netflix
  • Trello
  • Paypal
  • LinkedIn
  • Walmart
  • Uber
  • Medium
  • Groupon
  • Ebay
  • NASA

E a lista vai longe…

Vale a pena investir em JavaScript?

Dada a prevalência do JavaScript nas soluções baseadas no Node.js (incluindo TypeScript, que é transpilado para JavaScript), o investimento nesta linguagem é altamente vantajoso. Pesquisas anuais do Stack Overflow consistentemente classificam o JavaScript como uma das linguagens mais populares, reforçando sua relevância e demanda no mercado de desenvolvimento.

O Stack Overflow, reconhecida mundialmente como uma das comunidades mais influentes entre os desenvolvedores, realiza anualmente um levantamento detalhado sobre tecnologias, linguagens e tendências do setor de TI. Nas pesquisas realizadas de 2014 a 2021, a linguagem JavaScript destacou-se consistentemente, ocupando a posição de liderança no ranking das linguagens preferidas pelos desenvolvedores. Notavelmente, em 2013, o JavaScript ficou em segundo lugar, superado apenas pela linguagem SQL.

Em 2022:

Relatório 2022. Fonte: https://survey.stackoverflow.co/2022#most-popular-technologies-language

Acesse todos os relatórios em: https://insights.stackoverflow.com/survey

Esses dados reforçam claramente a existência de uma demanda significativa no mercado para profissionais com conhecimento em JavaScript. O fato de a procura por essa habilidade permanecer elevada por um período extenso não apenas sugere uma necessidade constante desses profissionais, mas também sinaliza uma evolução contínua da tecnologia, atendendo e superando as expectativas do setor.

Vai JavaScript, ao infinito e além! 🚀🚀 🚀

Top comments (0)