Executando verificação de segurança...
1

Node.js visualized: Event Loop

Já todos ouvimos falar do JavaScript e do Node.js serem single-threaded, mas o que é que isso significa em termos práticos?

Isto significa que o JavaScript pode fazer uma coisa de cada vez. Por exemplo, não podemos simultaneamente multiplicar e somar números. Normalmente fazemos operações em sequência. Adicionamos e depois multiplicamos ou vice-versa. Os computadores modernos são rápidos, e o resultado de duas ou mais tarefas consecutivas parece ser computado simultaneamente, mas há excepções.

Todos nós tentámos receber dados de um website lento ou esperámos mais de trinta segundos antes de obter o resultado de uma consulta a uma base de dados. Será que queremos bloquear o nosso único tópico de executar mais tarefas por causa de uma consulta lenta a uma base de dados? Felizmente, o Node.js não pára de executar outras operações devido à Libuv, uma biblioteca C++ responsável pelo loop do evento e pelo tratamento assíncrono de tarefas tais como pedidos de rede, resolução DNS, operações do sistema de ficheiros, encriptação de dados, etc.

O que acontece debaixo dos panos quando o Node.js trabalha em tarefas como a consulta de bases de dados? Iremos explorá-lo seguindo passo a passo este pedaço de código.

console.log('Start Node.js');

db.query("Select * FROM public.posts", functuion(err,res){
console.log('Query executada');
})

console.log('Antes do resultado da query')

Motor JavaScript V8 gere uma stack de chamadas, uma peça essencial que rastreia que parte do nosso programa está a correr. Sempre que invocamos uma função JavaScript, ela é empurrada para a pilha de chamadas. Assim que a função atinge o seu fim ou uma declaração de retorno, ela é empurrada para fora da stack.

No nosso exemplo, a linha de código console.log('Start Node.js') é adicionada à stack de chamadas e imprime Start Node.js para a consola. Ao fazê-lo, chega ao fim da função de registo e é removido da stack de chamadas.

exemplo

A seguinte linha de código é uma consulta a uma base de dados. Estas tarefas são imediatamente despoletadas porque podem demorar muito tempo. São passadas para a Libuv, que as trata de forma assíncrona em segundo plano. Ao mesmo tempo, o Node.js pode continuar a executar outro código sem bloquear o sua unica thread.

No futuro, Node.js saberá o que fazer com a consulta porque associámos uma função de chamada de retorno com instruções para lidar com o resultado da tarefa ou erro. No nosso caso, é uma simples consola.log, mas pode ser uma lógica empresarial complexa ou processamento de dados em aplicações de produção.

exemplo

Enquanto o Libuv trata da consulta em segundo plano, o nosso JavaScript não está bloqueado e pode continuar com console.log("Antes do resultado da query").

exemplo

Quando a consulta é feita, o seu retorno é empurrado para a Fila de Eventos I/O para ser executado em breve*.* O loop liga a fila com a stack de chamadas. Verifica se a última está vazia e move o primeiro item da fila para execução.

exemplo

Conclusão

O Event Loop, a delegação, e o mecanismo de processamento assíncrono são os ingredientes secretos do Node.js para processar milhares de ligações, ler/escrever ficheiros gigantescos, manusear temporizadores enquanto se trabalha noutras partes do nosso código.

No artigo, vimos o papel vital da Libuv e a sua capacidade de lidar com inúmeras tarefas potencialmente de longa duração. Ao mesmo tempo, passamos pelo Event Loop e o seu papel como ponte/conector entre as chamadas de retorno de operações assíncronas na fila de eventos I/O e a pilha de chamadas. Nos artigos seguintes, iremos explorar em maior detalhe como os temporizadores, E/S, promessas e ticks são tratados pelas diferentes fases do Event Loop.

Carregando publicação patrocinada...