Skip to content

Capítulo 4.5: Async/await vs Promise

Tempo de estudo: 30 minutos


1. Assincronicidade: Duas maneiras de gerenciar a "comunicação espacial"

Imagine que o Centro de Controle da Missão (CCM) envie um comando para Marte. A resposta só chegará em alguns minutos. Como organizar o trabalho durante esse tempo?

Maneira 1: "Protocolo de Retorno de Chamada" (Promise com .then()) Você envia um comando e dá uma instrução: "QUANDO a resposta chegar, ENTÃO execute esta função". Isso é parecido com uma cadeia de eventos.

Maneira 2: "Modo de Espera" (Async/await) Você diz: "Eu VOU ESPERAR a resposta para este comando, mas não vou bloquear outros consoles de controle". É como se você pausasse a execução desta tarefa específica, permitindo que o resto do CCM continue trabalhando.

Ambas as maneiras resolvem a mesma tarefa — gerenciar operações assíncronas. async/await é simplesmente uma sintaxe mais moderna e legível que funciona "em cima" das promises.

💡 Analogia espacial:

  • Promise com .then(): É como escrever num post-it: "Quando o rover de Marte enviar a foto, encaminhá-la para o departamento de análise".
  • Async/await: É como dizer ao assistente: "Espere pela foto do rover de Marte, enquanto isso vou fazer os cálculos para o lançamento de um novo foguete".

2. Promise com .then(): Cadeia de comandos clássica

Esta é a maneira fundamental de trabalhar com assincronicidade em JavaScript, que usamos no Capítulo 4.1.

Vamos relembrar nosso primeiro código:

function getIssPositionWithPromises() {
    console.log('Enviando solicitação via protocolo "Promise"...');

    fetch('http://api.open-notify.org/iss-now.json')
        .then(response => {
            // Etapa 1: Resposta recebida
            if (!response.ok) {
                throw new Error(`Erro HTTP: ${response.status}`);
            }
            return response.json(); // Retornamos uma nova promise
        })
        .then(data => {
            // Etapa 2: Dados analisados
            console.log('Dados via protocolo "Promise" recebidos:', data.iss_position);
        })
        .catch(error => {
            // Etapa 3 (Erro): Algo deu errado em qualquer uma das etapas
            console.error('Falha de comunicação via protocolo "Promise":', error);
        });

    console.log('...comando enviado, CCM continua trabalhando...');
}

Vantagens:

  • Cadeia explícita de ações.
  • Adequado para operações sequenciais simples.

Desvantagens:

  • "Inferno de Callbacks" (Callback Hell): Com um grande número de operações assíncronas aninhadas, o código pode se transformar numa "escadaria" de .then(), o que dificulta a leitura.
  • O tratamento de erros pode ser menos intuitivo.

3. Async/await: Estilo síncrono moderno

async/await é "açúcar sintático" sobre promises, que permite escrever código assíncrono como se fosse síncrono.

Regras de uso:

  1. A palavra-chave await pode ser usada apenas dentro de uma função marcada como async.
  2. await é colocado antes de uma chamada que retorna uma promise (por exemplo, fetch() ou response.json()).
  3. await "pausa" a execução da função async até que a promise seja resolvida, e retorna o seu resultado.

O mesmo código, reescrito com async/await:

async function getIssPositionWithAsyncAwait() {
    console.log('Enviando solicitação via protocolo "Async/await"...');

    try {
        // Etapa 1: Esperando resposta do servidor
        const response = await fetch('http://api.open-notify.org/iss-now.json');

        if (!response.ok) {
            throw new Error(`Erro HTTP: ${response.status}`);
        }

        // Etapa 2: Esperando que o corpo da resposta seja convertido para JSON
        const data = await response.json();

        console.log('Dados via protocolo "Async/await" recebidos:', data.iss_position);
    } catch (error) {
        // Etapa 3 (Erro): Capturamos qualquer erro do bloco try
        console.error('Falha de comunicação via protocolo "Async/await":', error);
    }

    console.log('...comando enviado, CCM continua trabalhando...');
}

Vantagens:

  • Legibilidade: O código parece quase um código síncrono comum, é fácil de ler de cima para baixo.
  • Tratamento de erros: Usa o bloco try...catch padrão e familiar.
  • Depuração: Muito mais fácil de depurar, pois você pode colocar pontos de interrupção (breakpoints) em cada linha com await.

Desvantagens:

  • Fácil esquecer await ou async, o que levará a erros.

4. Quando usar qual protocolo?

Situação Abordagem recomendada Porquê?
Maioria dos casos async/await O código é mais limpo, mais fácil de ler e depurar. Este é o padrão moderno.
Cadeia simples de 1-2 ações Promise com .then() Totalmente adequado, o código permanece compacto.
Execução paralela de várias requisições Promise.all() Este método permite executar várias promises simultaneamente e esperar que todas sejam concluídas. async/await combina perfeitamente com ele.

Exemplo com Promise.all():

async function getParallelData() {
    try {
        // Executamos ambas as requisições simultaneamente
        const [shipsResponse, launchesResponse] = await Promise.all([
            fetch('https://api.spacexdata.com/v4/rockets'),
            fetch('https://api.spacexdata.com/v4/launches/latest')
        ]);

        if (!shipsResponse.ok || !launchesResponse.ok) {
            throw new Error('Uma das requisições falhou!');
        }

        const rockets = await shipsResponse.json();
        const latestLaunch = await launchesResponse.json();

        console.log(`Total de foguetes na frota: ${rockets.length}`);
        console.log(`Último lançamento: ${latestLaunch.name}`);
    } catch (error) {
        console.error('Erro ao obter dados paralelos:', error);
    }
}


Quiz para fixação

1. `async/await` é...

2. Qual palavra-chave é obrigatória para uma função dentro da qual `await` é usado?

3. A principal vantagem de `async/await` sobre `.then()`:

4. O que acontece se você esquecer `await` antes de `fetch()` dentro de uma função `async`?

5. `Promise.all()` é usado para:


🚀 Resumo do Capítulo:

Você aprendeu duas sintaxes para gerenciar operações assíncronas e entendeu por que async/await é preferível na maioria dos projetos modernos.

  • 🔗 Você revisou seus conhecimentos sobre Promise com .then().
  • 🛠️ Você compreendeu profundamente como funciona async/await e suas vantagens.
  • ⚡ Você aprendeu sobre Promise.all para executar requisições paralelas.

Protocolos de comunicação aprendidos! No capítulo final desta seção, reuniremos todo o nosso conhecimento e construiremos nosso "Centro de Controle de Voo", criando uma interface completa para todas as operações CRUD.

📌 Prática:

  • Reescreva todas as funções em seu app.js que ainda usam .then(), para a sintaxe async/await.
  • Tente adicionar mais uma requisição a Promise.all() (por exemplo, para https://api.spacexdata.com/v4/starlink) e exiba os dados.

⚠️ Se houver erros:

  • await is only valid in async functions: Certifique-se de que a função onde você usa await esteja marcada como async.
  • A variável contém [object Promise]: Você esqueceu de colocar await antes da função que retorna uma promise.