JS-0601 - JavaScript Completo ES6 - Assincronismo

Entendendo o fluxo de execução
A assincronia na execução de tarefas é uma das partes mais importantes do JavaScript moderno. Para a entender, primeiramente é necessário o entendimento sobre o sincronismo.
Na maioria das vezes, a implementação de um código segue um fluxo: execução, retorno da execução, próxima execução... sequencialmente. Enquanto não houver o retorno, o código fica pausado, trabalhando com uma única thread (JavaScript é single threaded).
As aplicações Web exigem diversos tipos de requisições para diferentes tipos de aplicações consecutivamente ou em paralelo. A espera pelo término de tarefas comprometeria sensivelmente uma aplicação, pois se para cada requisição fosse necessário o aguardo de uma resposta, a aplicação seria carregada aos poucos e aos trancos..
Para permitir a continuidade de execução de tarefas que não dependam de respostas sobre as outras, foram implementados ao JS funções de callback assincronas (async), promises, fetch, ajax entre outros (serão abordados adiante), além do já citado setTimeout. Estas funções são deslocadas para as suas respectivas stacks quando carregadas na Web API, e não "prendem" a execução das demais tarefas, ficando no pano de fundo e realizando suas funções assim que possível.
Um exemplo simples e curioso que permite visualizar a sequência de execução de eventos pode ser vista abaixo. Tente primeiramente pensar em qual será a ordem de retorno, depois visualize o resultado:

Entendendo o ocorrido:
- A primeira função setTimeout, assíncrona e anônima, com tempo de execução imediato (0 milissegundos), é resolvida na Web API e colocada na Task Queue;
- A segunda função setTimeout, assíncrona e anônima, com tempo de execução de 100 milissegundos, é resolvida na Web API e permanece aguardando seu tempo de execução transcorrer para depois ir para a Task Queue;
- O primeiro console.log é resolvido na Web API, é executado na Call Stack e retorna o valor;
- A terceira função setTimeout, assíncrona e anônima, com tempo de execução de 50 milissegundos, é resolvida na Web API e permanece aguardando seu tempo de execução transcorrer para depois ir para a Task Queue;
- O segundo console.log é resolvido na Web API, é executado na Call Stack e retorna o valor;
- A Call Stack é esvaziada, começam as tarefas da Task Queue (assíncronas) em um loop;
- A primeira função setTimeout vai para a Call Stack, executa o seu callback (console.log) e retorna o valor;
- A segunda função setTimeout ainda permanece aguardando o tempo zerar para depois ir para a Call Stack;
- O tempo da terceira função setTimeout chega a zero, vai para a Call Stack, executa o seu callback (console.log) e retorna o valor; e
- O tempo da segunda função setTimeout chega a zero, vai para a Call Stack, executa o seu callback (console.log) e retorna o valor.
Desta forma, há diversas vantagens através do assincronismo, em background, do JS, que evitam travamentos, permitem a utilização das demais funcionalidades da aplicação, possibilitam a execução de funções de acordo com as respostas de requisições ao servidor e a atualização de dados na página sem a necessidade de refresh desta.