# Javascript Assíncrono - Fluxo assíncrono e Event Loop

No [artigo anterior](https://carlosvaz.com.br/javascript-assincrono-entenda-o-que-sao-callbacks) aprendemos o que são callbacks e como funcionam, esse conhecimento é importante para termos o entendimento suficiente para compreender o conteúdo desse artigo e os demais da série.
Aqui, iremos entender sobre o fluxo assíncrono do Javascript.

## Fluxo síncrono
Antes disso vamos recapitular novamente o que é fluxo síncrono. Segue abaixo um exemplo.
```
1 console.log('Início do cálculo');
2 const resultado = 2 + 2;
3 console.log('Resultado é igual a:', resultado);
4 console.log('Fim do cálculo');
```

O resultado que aparecerá na tela (ou console) será:

```
Início do cálculo
Resultado é igual a: 4
Fim do cálculo
```

Como era de se esperar, o código foi executado linha por linha, da 1 até a linha 4, nessa sequência, de modo síncrono.

Por enquanto não há nenhum mistério por aqui, certo?

Javascript é ***single threaded***, ou seja, opera em uma única thread, se você executar com código síncrono e por alguma eventualidade um comando bloquear a thread principal, o seu navegador (ou script no caso do node) irá travar até que a operação seja concluída.

Abaixo segue um bom exemplo adicionando o comando `alert()` no código anterior.
```
1 console.log('Início do cálculo');
2 const resultado = 2 + 2;
3 alert('Clique para continuar');
3 console.log('Resultado é igual a:', resultado);
4 console.log('Fim do cálculo');
```
Se executarmos esse código no navegador, a linha 1, 2 e 3 serão executadas. A terceira linha irá lançar um alerta na tela, isso irá bloquear o navegador, não permitindo nenhuma outra interação do usuário, ao menos que ele pressione o botão `Ok` do alerta. Após o clique no botão `Ok` as linhas 3 e 4 serão executadas.

Qual é o problema desse tipo de execução? imagina uma aplicação web como facebook, home banking, webmail ou youtube, se todo comando de pesquisa, ação de abrir um email ou execução de um vídeo bloqueasse a tela?

Essa maneira síncrona de execução é ruim porque não sabemos quanto tempo um vídeo será carregado, uma imagem será baixada ou uma resposta de um serviço será retornada, e pior, se ocorrerá um erro ou não.


## Fluxo assíncrono

O que é assíncrono? de acordo com o dicionários na web:
> Assíncrono: Que não ocorre ou não se efetiva ao mesmo tempo, que não acontece juntamente com outra coisa.


No YouTube, por exemplo, quando um vídeo está sendo carregado ou executado, essa operação é assíncrona, ela não bloqueia a tela do navegador, você pode realizar outra interação na tela do aplicativo web ao mesmo tempo que outras operações estão ocorrendo de forma assíncrona.

Mas como é possível execuções paralelas visto que o Javascript é *single thread*?

Agora vamos entrar em uma parte bem interessante, entender como o fluxo assíncrono funciona e assim responder a essa pergunta.

### Call Stack
É o mecanismo do interpretador do Javascript, ele adiciona as funções para serem executa uma por vez, assim que forem executados ele remove da pilha.

> Aqui nesse artigo vamos utilizar o [loupe](http://latentflip.com/loupe) para simular como funciona o runtime do Javascript.

Abaixo um exemplo de sequência de execução de linhas contendo comandos *console.log*, você verá cada linha sendo executada e logo após removida do Call Stack.


![Exemplo de código síncrono sendo executado loupe](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oqc9da3jfbdhkcw6k8wx.gif)
[Código da imagem acima no loupe](http://latentflip.com/loupe/?code=Cgpjb25zb2xlLmxvZygnMScpOwpjb25zb2xlLmxvZygnMicpOwpjb25zb2xlLmxvZygnMycpOwpjb25zb2xlLmxvZygnNCcpOwo%3D!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D)



Como falamos anteriormente, o Javascript é  ***single threaded***, podemos ver isso na ***Call Stack***, código mal implementado pode bloquea-la facilmente. Abaixo podemos ver um comando *while* sendo executado infinitamente, o que acaba ocasionando o bloqueio da *Call Stack*


![Exemplo de bloqueio da call stack ocasionado por um loop infinito](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jk3261vffqxlveodzfpv.gif)
[Código da imagem acima no loupe](http://latentflip.com/loupe/?code=Cgpjb25zb2xlLmxvZygnMScpOwpjb25zb2xlLmxvZygnMicpOwpjb25zb2xlLmxvZygnMycpOwp3aGlsZSh0cnVlKSB7CiAgY29uc29sZS5sb2coJ0VudHJvdSBubyB3aGlsZSBpbmZpbml0bycpOwp9Cgpjb25zb2xlLmxvZygnNCcpOw%3D%3D!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D)
 
Agora um novo exemplo de funções sendo adicionadas na *Call Stack*.

![Empilhamento de funções na call stack](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4vkkgy3lkyk5hd9fwhb2.gif)
[Código da imagem acima no loupe](http://latentflip.com/loupe/?code=CgpmdW5jdGlvbiBmbjMoKSB7CiAgY29uc29sZS5sb2coJ0ZuMycpOwp9CgpmdW5jdGlvbiBmbjIoKSB7CiAgZm4zKCk7Cn0KCmZ1bmN0aW9uIGZuMSgpIHsKICBmbjIoKTsKfQoKZnVuY3Rpb24gbWFpbigpIHsKICBmbjEoKTsKfQoKbWFpbigpOwo%3D!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D)

Agora que entendemos com funciona a *Call Stack* vamos aprofundar o entendimento da parte assíncrona do Javascript, com explicações sobre ***Web APIs***, ***Callback Queue*** e ***Event Loop***.

### Web APIs

Os navegadores fornecem Api's com funções assíncronas que podemos utilizar no nosso código, elas são executadas separadamente da Call Stack, evitando o seu bloqueio e realizando a execução em paralelo ao restando dos códigos.

### Callback Queue
Quando utilizamos uma função assíncrona da Api do javascript, normalmente queremos reagir ao resultado dessa função, como por exemplo dados recebidos de uma chamada externa ou conteúdo de algum arquivo lido do disco local. Nesse momento entra a principal função dos ***callbacks***, eles serão chamados quando função principal terminar sua execução e repassando para eles os seus resultados.
Após isso os callbacks serão colocados na ***Callback queue***, e aguardar até que a ***Call Stack*** esteja vazia para serem executados.

### Event Loop
O ***Event Loop*** irá pegar o primeiro callback da ***Callback Queue*** e adicionar na ***Call Stack*** assim que a mesma estiver vazia. Se na Call Stack contiver algum código o Event Loop será bloqueado e não adicionará nenhum chamada até que a pilha esteja vazia.

Abaixo segue um exemplo utilizando ***setTimeout*** do Javascript, ele é uma função assíncrona que recebe um callback como parâmetro.

![event_loop_04_callback_queue.gif](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xpjucxxqkytgcy2j25zm.gif)
[Código da imagem acima no loupe](http://latentflip.com/loupe/?code=CgpmdW5jdGlvbiBidXNjYURhZG9zKCkgewogIHNldFRpbWVvdXQoZnVuY3Rpb24gc2ltdWxhQ29uc3VsdGFBcGkoKSB7CiAgICBjb25zb2xlLmxvZygnRGFkb3MgcmV0b3JuYWRvcycpOwogIH0sIDMwMDApOwp9CgpmdW5jdGlvbiBmdW5jYW8wMSgpIHsKICBidXNjYURhZG9zKCk7CiAgY29uc29sZS5sb2coJ2Z1bmNhbzAxJyk7Cn0KCmZ1bmN0aW9uIG1haW4oKSB7CiAgY29uc29sZS5sb2coJ0luaWNpYW5kby4uLicpOwogIGZ1bmNhbzAxKCk7Cn0KCm1haW4oKTsKY29uc29sZS5sb2coJ0ZpbSEnKTsK!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D)

Agora vamos entender passo a passo do exemplo acima:
1. Na linha `19` a função `main()` é chamada e colocada na *Call Stack*;
2. Ao executar a função `main()` o javascript lê o comando `console.log('Iniciando...')` da linha `15`, coloca na `Call Stack` e o executa, logo após o comando é removido da pilha;
3. Na linha `16` a função `funcao01()` é chamada e colocada na `Call Stack`;
4. Ao executar a função `funcao01()`, encontramos na linha `10` a chamada para a função `buscaDados()`, a mesma é colocada na `Call Stack`;
5. Ao ler a função `buscaDados()`, o javascript encontra na linha `4` o comando `setTimeout`, como ele é uma função assíncrona o javascript o coloca na fila `Web Apis` para ser executado, aguardará 3 segundos e após isso seu callback `simulaConsultaApi()` é movido para a `Callback Queue`, para aguardar seu momento para entrar na `Call Stack`;
6. Nesse momento temos na `Call Stack`, do topo da fila para baixo, as seguintes funções: `buscaDados`, `funcao01` e `main`;
7. Continuando no fluxo da `Call Stack`, a função `buscaDados` é removida da fila;
8. O fluxo continua na linha `11`, onde o comando `console.log('funcao01')`, é colocado na `Call Stack`, e após a sua execução ele é removido da pilha;
9. A função `funcao01()` é removida da `Call Stack`;
10. A função `main()` é removida da `Call Stack`;
11. O fluxo segue na linha `20`, o comando `console.log('Fim!')` é colocado na `Call Stack` e executado, logo após é removido;
12. Como a fila da `Call Stack` está vazia, o `Event Loop` irá pegar o `callback simulaConsultaApi()` e coloca-la na `Call Stack`;
13. Ao executar o `callback simulaConsultaApi()`, o comando `console.log('Dados retornados')` da linha `5` será posto na `Call Stack`, executado e logo após removido.
14. E para finalizar, o `callback simulaConsultaApi()` será removido da `Call Stack` e o programa será finalizado.

Resumindo:
O funcionamento em paralelo de funções no Javascript consiste em pegar funções assíncronas e coloca-las na Web Apis para serem executadas em paralelo a Call Stack. Ao finalizar sua execução ela pega o callback que lhe foi fornecido com o resultado e o coloca na Callback Queue, quando a Call Stack estiver vazia o Event Loop joga o callback na Call Stack para ser executado.

## Conclusão
Essa explicações foram bem superficiais mas muito importantes para entendermos o que ocorre "por baixo do capô" do Javascript.
Nos próximos artigos da série iremos entrar em mais detalhes e entender sobre ***Promises*** e ***Async/Await***.

Espero que tenham gostado! Se puderem, deixem seus comentários e feedbacks :)

### Referências
- https://www.youtube.com/watch?v=8aGhZQkoFbQ
