Javascript assíncrono: Promises

Pedro Costa
4 min readJul 11, 2022
Callback Hell. Ninguém quer fazer a manutenção disso. Por isso nasceram as Promises.

Se você chegou nesse post, acredito que tenha interesse em Javascript e venha se perguntado ‘What the hell é um código assíncrono’ e ‘O que são Promises’?

Vou responder essa pergunta decompondo a questão em algumas partes: o que é, e qual a necessidade de um código assíncrono? Como eles funcionam em Javascript, com as famosas Promises? Como escrever, de forma compreensível, uma Promise? Veremos tudo com exemplos.

Em breve volto com novo post para explicar o async/await, novidade do ES8 pra simplificar o trabalho com Promises.

O que é código assíncrono?

Ao escrever tuas linhas de código como desenvolvedor, você costuma considerar que o primeiro código escrito será o primeiro executado. Há uma ordem, uma sequência no tempo, ou seja, há sincronia.

A linha seguinte só vai rodar quando a anterior terminar sua execução. Isso é um código síncrono.

O código assíncrono não é mais do que a situação oposta: uma linha de código começa a rodar — como exemplo, a leitura de um arquivo que demore alguns segundos — e no meio tempo o resto do código continua a ser executado, sem esperar pelo fim da execução anterior.

Chamei second antes, mas a execução foi só depois da ‘setTimeout’ aguardar 2 segundos. O resto do código seguiu rodando, de forma que ‘Terceiro’ foi pro console antes.

Código assíncrono é isso.

“Só isso?” SIM. “E eu com isso?” Boa pergunta…

Por que precisamos de código assíncrono?

Na web, muitas tarefas podem custar tempo até serem executadas. Se você vai buscar um dado numa API, pode levar um tempo até a resposta chegar. Se você vai rodar um algoritmo complexo no seu backend, pode passar um tempo até ele retornar. Não queremos que todo nosso código fique esperando uma única tarefa pra continuar sua execução. Ninguém gosta de perder tempo, principalmente o usuário de um site ou app.

O código assíncrono permite que você faça a leitura da maior parte do seu código, isolando a execução de tarefas demoradas até que elas tenham sido executadas. Assim, você pode fazer uma query numa API logo no início do código, e enquanto aquele processo acontece, você já está processando todos os outros dados, até que aquela tarefa termine de ser executada.

E quando terminar a execução? Então você pode chamar de volta (callback) aquela função, e tratar (handle) os dados que ela retornou, ou deixou de retornar (erro). Esse trabalho, de anunciar primeiro e lidar com o resultado depois, é tarefa da Promise.

O uso das promises permite que o código não fique refém da organização síncrona, que pode criar um grande encadeamento de funções que dependem umas das outras, levando ao famigerado Callback Hell, como se vê na primeira imagem.

O que são Promises?

Considere a seguinte situação: eu quero ir à praia no feriado, essa é minha pretensão, ou promessa (Promise). O feriado ainda não chegou, então vou esperar até tomar alguma atitude, mas já sei os dois desfechos possíveis pra esse plano: se chover, fico em casa. Se não chover, vou pra praia.

Vamos transformar essa história num código que retorna uma Promise.

A função feriadoNaPraia tem como retorno uma Promise.

Criamos uma nova Promise com new Promise(), que recebe como argumento uma função no formato (resolve, reject) => {}.

Resolve e reject são padrões do Javascript para lidar com a Promessa cumprida ou não. Dentro da Promise, usamos uma setTimeout() pra esperar pelo feriado, e quando chega o dia, verificamos se está chovendo ou não. Se não chove, resolvemos a Promise com sucesso e vamos pra praia. Se chove, a Promise é rejeitada.

A seguir, vemos como lidar com a Promise usando os métodos THEN, CATCH e FINALLY.

A promessa foi feita no código anterior, criamos uma maneira de lidar com o resolução ou rejeição da promessa ainda no texto da Promise, e agora voltamos a chamar aquela função feriadoNaPraia, respondendo finalmente se a chuva havia chegado ou não. No caso, já imputei um true, mas poderia ter colocado o resultado de um outro processo ali. O THEN trabalha com a Promise aceita, o CATCH com a Promise rejeitada, e o FINALLY é executado em ambos os cenários.

É comum fazer referência ao estado da Promise. Ela pode se encontrar de 4 maneiras diferentes:

  • Pendente(pending): foi criado, mas não teve qualquer desfecho.
  • Resolvida(resolved): obteve sucesso, sendo chamado o método resolveI().
  • Rejeitada(rejected): foi negada, chamando reject().
  • Estabelecida(settled): foi resolvida ou rejeitada, isto é, não está pendente.

Por fim, a sequência do código criado acima, com seu output. Espero que o post tenha esclarecido o funcionamento das promises e o significado do código assíncrono. Em breve um post sobre async/await pra facilitar a vida, mas é bom saber que eles dependem da Promise!

--

--