O que você é, Event Loop? Ou como o loop de eventos funciona no navegador Chrome

O que você acha que acontecerá se você executar esse código no console do navegador?

function foo() { setTimeout(foo, 0); } foo(); 

E esse aqui?

 function foo() { Promise.resolve().then(foo); } foo(); 

Se você, como eu, leu vários artigos sobre Loop de Eventos, Tópico Principal, tarefas, microssefas e muito mais, mas acha difícil responder às perguntas acima - este artigo é para você.

Então, vamos começar. O código para cada página HTML no navegador é executado no Thread Principal . Thread principal é o thread principal em que o navegador executa JS, redesenha, manipula ações do usuário e muito mais. Essencialmente, é aqui que o mecanismo JS é integrado ao navegador.

A maneira mais fácil de descobrir isso é observando o diagrama:


Figura 1

Vemos que o único local através do qual as tarefas podem entrar na pilha de chamadas e concluir é o loop de eventos. Imagine que você estava no lugar dele. E seu trabalho é acompanhar as tarefas. As tarefas podem ser de dois tipos:

  1. Pessoal - execução do principal código JavaScript no site (a seguir assumimos que ele já foi executado)
  2. Tarefas do cliente - Renderização, microtaks e tarefas

Provavelmente, suas tarefas pessoais serão priorizadas. O Event Loop concorda com isso :) Resta otimizar as tarefas do cliente.

Obviamente, a primeira coisa que vem à mente é dar prioridade a cada cliente e alinhá-los. O segundo é determinar exatamente como as tarefas de cada cliente serão processadas - uma de cada vez, todas de uma vez ou talvez em lotes.

Dê uma olhada neste diagrama:


Figura 2

Com base nesse esquema, todo o trabalho do Event Loop é construído.
Depois que começamos a executar qualquer script, a tarefa com a execução desse script é colocada na fila de tarefas. À medida que esse código é executado, encontramos tarefas de diferentes clientes, que são colocadas na fila apropriada. Após a conclusão da tarefa de execução do script (tarefa de Tarefas), o Loop de Eventos vai para Microtasks (após a tarefa de Tasks, o Event Loop executa tarefas das Microtasks). O Loop de Eventos recebe tarefas dele até que elas terminem . Isso significa que, se o tempo de adição for igual ao tempo de execução, o Loop de Eventos os varrerá infinitamente.
Em seguida, ele vai para Render e executa tarefas dele. As tarefas do Render são otimizadas pelo navegador e, se considerar que não há necessidade de redesenhar nada neste ciclo, o Event Loop simplesmente irá além. Em seguida, o Event Loop pega novamente as tarefas do Tasks e solicita apenas uma, a primeira tarefa na fila , a transfere para o CallStack e vai mais longe no loop.

Se um dos clientes não tiver tarefas, o Event Loop passará para o próximo. E, pelo contrário, se as tarefas do cliente demorarem muito, os clientes restantes aguardarão a sua vez. E se as tarefas de algum cliente acabaram sendo infinitas, a Pilha de chamadas transborda e o navegador começa a jurar:


Figura 3

Agora que entendemos como o Loop de eventos funciona, é hora de descobrir o que acontece depois que os trechos de código são executados no começo deste artigo.

 function foo() { setTimeout(foo, 0); } foo(); 

Vemos que a função foo se chama recursivamente através de setTimeout, mas a cada chamada cria uma tarefa do cliente Tasks. Como lembramos, no loop Event Loop, ao executar a fila de tarefas do Tasks, são necessárias apenas 1 tarefa no loop. E há tarefas do Microtasks e Render. Portanto, esse trecho de código não fará com que o Loop de Eventos sofra e atrapalhe para sempre suas tarefas. Mas lançará uma nova tarefa para as tarefas do cliente em cada volta.

Vamos tentar executar esse script no navegador Google Chrome. Para fazer isso, criei um documento HTML simples e liguei o script.js com esse trecho de código. Depois de abrir o documento, acesse as ferramentas do desenvolvedor e abra a guia Perfomance e clique no botão 'iniciar perfil e recarregar página':


Figura 4

Vemos que as tarefas do Tasks são executadas uma de cada vez, aproximadamente uma vez a cada 4ms.

Considere o segundo quebra-cabeça:

 function foo() { Promise.resolve().then(foo); } foo(); 

Aqui vemos o mesmo que no exemplo acima, mas chamar foo adiciona tarefas do Microtasks, e tudo é feito até o fim. Isso significa que, até que o loop de eventos termine, ele não poderá passar para o próximo cliente :( E novamente vemos uma imagem triste.

Dê uma olhada nisso nas ferramentas de desenvolvimento:


Figura 5

Vemos que as microtaks são executadas aproximadamente uma vez a cada 0,1 ms, e isso é 40 vezes mais rápido que a fila de tarefas. Tudo porque eles são executados de uma só vez. No nosso exemplo, a fila se move infinitamente. Para visualização, reduzi-o para 100.000 iterações.

Isso é tudo!

Espero que este artigo tenha sido útil e agora você entenda como o Loop de eventos funciona e o que está acontecendo nos exemplos de código acima.

Tchau :) E até breve. Se você gostou, curta e assine o meu canal :)

Source: https://habr.com/ru/post/pt461401/


All Articles