async await javascript: guia completo e prático
Async e await simplificam o trabalho com Promises em JavaScript. Neste guia, você aprende na prática a escrever código assíncrono legível, evitar erros comuns e melhorar a manutenção do seu projeto.

Se você já tentou encadear várias Promises com .then() e se perdeu em meio a parênteses e retornos, async e await existem para isso: tornar o código assíncrono mais direto. Neste guia, vamos construir uma função assíncrona passo a passo, entender o papel de cada palavra-chave e apontar os erros que mais derrubam quem está começando. Ao final, você terá um critério claro para decidir quando usar async/await e quando ainda vale recorrer a .then().
Pré-requisito: conhecimento básico de funções e de Promises em JavaScript. Se você nunca viu uma Promise, vale revisar o conceito antes de seguir.
Passo 1: Entenda a função async
A palavra-chave async antes de uma função faz duas coisas: ela define que a função sempre retorna uma Promise e permite o uso de await dentro dela. Mesmo que você retorne um valor simples, como uma string, o JavaScript o envolve em uma Promise resolvida.
async function saudacao() { return "Olá"; }
saudacao().then(console.log); // Olá
Erro comum: achar que async torna a função automática e instantaneamente assíncrona. Não é isso. async apenas garante o retorno de uma Promise. A assincronicidade real vem do await e das operações que você coloca dentro da função.
Passo 2: Use await para pausar a execução
await só funciona dentro de funções async. Ele pausa a execução da função até que a Promise à direita seja resolvida, e então retorna o valor resolvido. Na prática, você escreve código que parece síncrono, mas não bloqueia o restante do programa.
async function buscarDados() { const resposta = await fetch("https://api.exemplo.com/dados"); const dados = await resposta.json(); return dados; }
Dica: use await apenas quando você realmente precisa do valor da Promise para continuar. Se duas Promises não dependem uma da outra, use Promise.all para executá-las em paralelo, em vez de aguardar uma após a outra. Isso reduz o tempo total de espera.
Passo 3: Trate erros com try/catch
Código assíncrono falha. Rede instável, API fora do ar, resposta inesperada. Com async/await, o tratamento de erros fica igual ao de código síncrono: use try/catch.
async function carregarPerfil(id) { try { const resposta = await fetch(/api/perfil/${id}); if (!resposta.ok) throw new Error("Falha na requisição"); return await resposta.json(); } catch (erro) { console.error("Erro ao carregar perfil:", erro); return null; } }
Erro comum: deixar o catch genérico e silencioso. Se você só faz console.log(erro) e retorna undefined, quem chama a função não sabe se houve falha ou se o dado é simplesmente vazio. Prefira retornar um valor explícito de erro ou lançar uma exceção tratada em nível superior.
Passo 4: Lide com rejeições fora do try/catch
Nem todo await precisa estar dentro de um try/catch. Se você está em uma função async que é chamada por outra função async, pode deixar o erro propagar e tratá-lo no nível mais alto. Isso evita try/catch aninhados e mantém o fluxo limpo.
async function buscarUsuario() { const usuario = await fetch("/api/usuario").then(r => r.json()); return usuario; }
async function main() { try { const usuario = await buscarUsuario(); console.log(usuario); } catch (erro) { console.error("Falha no fluxo principal:", erro); } }
Dica: se você usa await dentro de um loop, cuidado. for...of com await executa as operações de forma sequencial, o que pode ser lento. Se a ordem não importa, use Promise.all com um map.
Passo 5: Saiba quando não usar async/await
Async/await não substitui tudo. Para operações que precisam de concorrência máxima, como várias requisições independentes, Promise.all com .then() pode ser mais direto. Também evite async/await em funções de callback de alto desempenho, como em alguns casos de Array.forEach, pois o await não funciona como esperado dentro de forEach (ele não pausa o loop).
// Errado: forEach não espera o await [1, 2, 3].forEach(async (id) => { await buscar(id); });
// Certo: for...of com await for (const id of [1, 2, 3]) { await buscar(id); }
Checklist do que você aprendeu
- [ ]
asyncdeclara uma função que sempre retorna Promise - [ ]
awaitpausa a execução até a Promise resolver, sem bloquear o programa - [ ] Use
try/catchpara tratar erros de forma explícita - [ ] Deixe erros propagarem quando o tratamento for feito em nível superior
- [ ] Evite
awaitemforEache loops onde a ordem importa
Perguntas frequentes sobre async e await em JavaScript
O que acontece se eu usar await fora de uma função async?
O JavaScript lança um erro de sintaxe. await só é válido dentro de funções declaradas com async. Em módulos ES, existe o suporte a await de nível superior, mas isso depende do ambiente de execução (Node.js 14.8+ ou navegadores modernos).
async/await substitui Promises?
Não. Async/await é uma sintaxe para consumir Promises, não uma alternativa a elas. Por baixo dos panos, continua tudo baseado em Promises. Você pode misturar os dois estilos, mas é recomendável manter consistência dentro do mesmo projeto.
Como executar duas Promises em paralelo com async/await?
Use Promise.all dentro de uma função async:
const [dados1, dados2] = await Promise.all([buscar(1), buscar(2)]);
Isso dispara as duas Promises simultaneamente e espera ambas resolverem.
Qual a diferença entre async/await e .then()?
A principal diferença é legibilidade. async/await torna o fluxo mais linear, especialmente quando há várias operações dependentes. .then() é mais flexível para encadeamento curto e concorrência. Não há diferença de desempenho significativa para a maioria dos casos.
await bloqueia o navegador?
Não. await pausa apenas a execução da função async, não o thread principal. O restante do código continua rodando normalmente. Isso é diferente de um loop síncrono que trava a interface.
Posso usar async/await em todos os navegadores?
Async/await é suportado em todos os navegadores modernos desde 2017. Para ambientes legados, você pode usar transpiladores como Babel, mas hoje isso raramente é necessário. Sempre verifique o público do seu projeto antes de descartar suporte.