Entendendo de uma vez por todas o que é ASYNC/AWAIT

Antes de entendermos como funciona o async/await nós precisamos entender sincronia e assincronia.


http://www.diogomatheus.com.br/blog/wp-content/uploads/2013/02/requisi%C3%A7%C3%A3o_sincrona_assincrona.jpg

A imagem é bem explicativa, mas não quero que vocês desvendem ela, quero que vocês entendam e para isso vou usar um exemplo, pode parecer bobo, mas pode tirar muitas dúvidas.

Imagina que você tem uma transportadora e sua empresa só tem um carro, porém você tem diversas entregas para fazer no dia, em vários bairros diferentes e para ajudar, seu carro é pequeno e não cabe muita coisa. A única solução para o seu problema é organizar melhor as rotas e se conformar que após terminar poucas entregas, você terá que voltar e buscar mais. Esse processo é síncrono, pois você precisa esperar ele terminar para você poder prosseguir com os próximos, ainda no exemplo, você precisa esvaziar o carro para então voltar na transportadora e pegar mais pacotes. Isso pode não ser um problema caso você tenha poucas entregas, ou trabalhe em poucas rotas, mas caso você precise escalar isso, pode vir a se tornar uma dor de cabeça.

A solução então seria comprar mais carros para que eles possam trabalhar ao mesmo tempo e em rotas diferentes?

Exato! Assim você não depende apenas de um carro para fazer as suas entregas, você tem outros e que podem fazer isso ao mesmo tempo. Nós podemos chamar esse processo de assíncrono.

É válido frisar que é apenas um exemplo lúdico para explicar o processo, preparar o terreno na sua cabeça sobre a diferença entre assincronia e sincronia na computação, mas o buraco é mais embaixo e dá para aprofundar bem mais o exemplo, mas não é o intuito desse artigo.


“Talk is cheap, show me the code!”

Quando aprendemos a programar temos o costume de trabalhar em blocos, principalmente quando aprendemos programação imperativa com código procedural. Naturalmente o fluxo é síncrono, mas depende muito da linguagem e como ela foi arquitetada.

Acima temos um exemplo síncrono, ou pelo menos desejamos que ele seja síncrono, tudo vai depender de como as funções removeUserWithAgeUnder30() e a função saveUsers() foram implementadas. Se ambas ou apenas uma for assíncrona, ou dentro do seu escopo elas usarem alguma função assíncrona o caos pode ter sido instaurado.

Como assim?

Bom, imagina a função saveUsers() sendo chamada antes da função removeUserWithAgeUnder30(). Se você reparar bem a função que salva os usuários pede um argumento que é justamente o resultado da função que remove os usuários com idade abaixo de 30. Viu o problema? Se você estiver trabalhando com funções assíncronas, isso pode acontecer. A função que salva os usuários pode muito bem no seu escopo usar uma função assíncrona do sequelize ou do mongodb para salvar os usuários no banco.

A função assíncrona asyncFunction() vai demorar 2 segundos para ser executada, com isso pode ser que a função síncrona syncFunction( ), que depende do resultado da função assíncrona, seja executada primeiro causando um erro, pois a variável number ainda está vazia.

A primeira forma de resolver isso é usando os métodos que a promise nos retorna, o método then().

Usando o then() a gente garante que o método syncFunction() só vai ser executado quando a promise for resolvida, basicamente a gente diz: “Já passaram os 2 segundos? A promise(promessa em pt-br) já foi resolvida? ENTÃO executa o próximo passo”.

Mesmo que amplamente usado, o then() pode vir a se tornar uma dor de cabeça também, pois imagina uma cadeia de “thens”:

Código extremamente ilegível e muito complicado de manutenir, pois você pode estender isso até onde quiser e ainda colocar regras, lógicas, etc…

Para contornar esse problema e organizarmos nossas funções assíncronas de modo que elas caminhem em sincronia quando necessário, de uma forma bem mais legível e elegante, temos a nossa carta na manga: ASYNC/AWAIT.

Simples, uma função simples com a palavra reservada ASYNC foi criada e dentro dela a gente usa o AWAIT para garantir que a função syncFunction() só seja executada após o termino da asyncFunction().

Aquele nosso exemplo da cadeia de “thens” com ASYNC/AWAIT ficaria bem mais legível e fácil de manutenir:

Por hoje é só e espero que de alguma forma esse artigo esclareça suas dúvidas!

Pedro Henrique Guimarães

Written by

Im 22, Back-end developer, Lucca’s dad and AI e FP enthusiast.