Event Loop - Dessa vez você aprende

Introdução

A ideia deste post é fornecer uma explicação simples do Event Loop. Ao final deste texto, você será capaz de ensinar ao seu filho e até mesmo à sua avó sobre o Event Loop.

Acredito que o processo de compreensão de um novo assunto deve começar com abstrações e simplificações. E, a partir daí, mais explicações, novos conceitos e detalhes específicos deverão ser agregados ao seu conhecimento. Minha sugestão para você: não tente absolver todo o contexto de uma vez, monte o quebra-cabeça peça por peça.

Então, com isso em mente, meu objetivo com este post é dar a você uma base para construir seu conhecimento sobre Event Loop. Como eu disse, o fundamento será apenas o básico, então, por enquanto, vou omitir alguns detalhes e conceitos avançados na explicação.

Vamos começar.

Conceitos iniciais

Callstack

Representa a pilha de execução JavaScript, o mecanismo pelo qual o JavaScript controla as chamadas de função em um programa.

Considere o código:

function f1() {
    console.log('Hi by f1!');
}

function f2() {
    f1();
}

f2();

Quando o programa for executado, ocorrerão as seguintes etapas:

  1. A chamada da função f2 será adicionada à pilha. Tamanho da pilha: 1
  2. A chamada da função f1 será adicionada à pilha. Tamanho da pilha: 2
  3. A chamada da função console.log será adicionada à pilha. Tamanho da pilha: 3
  4. console.log será executado e removido da pilha. Tamanho da pilha: 2
  5. f1 terminará e será removido da pilha. Tamanho da pilha: 1
  6. f2 terminará e será removido da pilha. Tamanho da pilha: 0

Microtask

É uma função executada após a função que a criou terminar e somente se a callstack do JavaScript estiver vazia. Alguns exemplos de microtarefas são as funções callback das Promises: .then, .catch e .finally.

Macrotask

Uma função que é executada após a callstack do JavaScript e a fila de microtasks terem sido limpas. As macrotask representam algum trabalho discreto e independente. Alguns exemplos de macrotask são as funções callback dos timers assíncronos: setTimeout, setInterval e setInterval.

O loop

O Event Loop é responsável por orquestrar a execução de código síncrono e assíncrono. Ele é executado continuamente enquanto o código Javascript está em execução.

Em muitos posts sobre Event Loop, você encontrará uma explicação excelente e detalhada de como ele funciona, as fases de execução e quais filas são gerenciadas. Bom, o foco aqui é fazer você entender o básico, então a explicação será bem simplificada. Mas lembre-se, esta é a sua base para aprender mais no futuro.

Vou pegar emprestada e descrever a ótima explicação apresentada no vídeo Aula Essencial de Javascript que Você Perdeu do canal Dev Junior Alves no YouTube.

O loop consiste em três fases:

  • Executar código síncrono e enfileirar microtasks e macrotasks
  • Executar as funções na fila de microtasks
  • Executar as funções na fila de macrotasks

Vamos entender esse processo usando este exemplo de código:

console.log("1");

setTimeout(() => {
    console.log("2");
}, 0);

Promise.resolve().then(() => {
    console.log("3");
});

console.log("4");

Antes de continuar, tente descobrir a saída do código com base apenas no seu conhecimento e no que foi dito acima.

Vamos continuar. A saída será:

1
4
3
2

Ok, por quê? Entenderemos a seguir.

Vamos ler o código novamente, mas com os conceitos iniciais e as três fases do Event Loop em mente.

// Um código síncrono, execute-o.
// Output: 1
console.log("1");

// Ah, uma função setTimeout, esta é uma macrotask.
// Vamos enviar o callback para a fila de macrotasks.
// Output: 1
setTimeout(() => {
    console.log("2");
}, 0);

// Hmm, uma Promise, uma microtask.
// Vamos enviar a callback .then para a fila de microtasks.
// Output: 1
Promise.resolve().then(() => {
    console.log("3");
});

// Outro código síncrono, execute-o.
// Output: 1 4
console.log("4");

// -----------------------------

// Ok, agora vamos executar a fila de microtasks:
// Output: 1 4 3

// Finalmente, vamos executar a fila de macrotasks:
// Output: 1 4 3 2

// Callstack, fila de microtasks e fila de macrotasks estão vazias.
// Então, FIM.

Próximos passos

Bom, agora você entende de forma simplificada como funciona o Event Loop. Não é mais um monstro de sete cabeças, talvez de três cabeças. A partir de agora cabe a você construir seu conhecimento acima dessa base.

"Como posso fazer isso?". Assista, leia e pratique até se cansar do Event Loop e até que ele se torne um conceito fixo em sua mente. Vou deixar links para alguns vídeos e posts abaixo.

E por fim, explique para outras pessoas: grave um vídeo, escreva um post no blog, faça uma call com um amigo, etc.

Espero que este post tenha sido útil para você! Vejo você na próxima :)

Links úteis

Vídeos

Posts

E no Node.JS o process.nextTick é considerado uma micro task ou uma macro task? pelo o que ja pesquisei na internet ela roda antes de todos os setImmediate então seria uma microtask?

Isso, ela é considerada uma microtask :)

Sensacional! Já havia pesquisado superficialmente sobre, mas nenhum dos conteúdos foi tão esclarecedor quanto a sua explicação, que foi direto ao ponto sobre como esses conceitos se integram.