Padrões async/await em JavaScript que você deve conhecer

Frontend2026-09-20TryQuickToolBox

A programação assíncrona é uma parte central do JavaScript moderno, e o async/await a tornou muito mais legível. Mas muitos desenvolvedores ainda enfrentam armadilhas comuns: rejeições de promises não tratadas, requisições sequenciais lentas ou tratamento de erros confuso. Neste artigo, vamos explorar padrões práticos de async/await que você pode aplicar imediatamente para escrever código mais limpo e eficiente.

1. Sintaxe básica de async/await

Uma função async sempre retorna uma Promise. A palavra-chave await pausa a execução até que a Promise seja resolvida, e então retorna seu valor resolvido. Se a Promise for rejeitada, ela lança um erro que você pode capturar com try/catch.

async function fetchData() {
  try {
    const response = await fetch('/api/data');
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Fetch failed:', error);
  }
}

Esta é a base. Mas cenários do mundo real frequentemente exigem abordagens mais detalhadas.

2. Tratando erros com elegância

Uma das maiores vantagens do async/await é que você pode usar try/catch tanto para erros síncronos quanto assíncronos. No entanto, tenha cuidado com múltiplas chamadas await em um único bloco try: se a primeira falhar, as subsequentes não serão executadas.

Para maior granularidade, você pode envolver cada await em seu próprio try/catch ou usar uma função auxiliar para evitar blocos try/catch repetitivos.

async function getUser(id) {
  try {
    const user = await fetchUser(id);
    return user;
  } catch (error) {
    console.error('Failed to fetch user:', error);
    throw error;
  }
}

3. Executando promises em paralelo

Aguardar múltiplas promises independentes sequencialmente é um erro de desempenho comum. Se você precisa de resultados de várias fontes, use Promise.all() para executá-las simultaneamente.

// Sequencial: lento
const user = await fetchUser();
const posts = await fetchPosts();

// Paralelo: rápido
const [user, posts] = await Promise.all([fetchUser(), fetchPosts()]);

Use Promise.allSettled() quando quiser esperar que todas as promises sejam resolvidas ou rejeitadas. Isso é útil quando você deseja coletar resultados mesmo que algumas falhem.

4. Execução sequencial quando a ordem importa

Às vezes você precisa processar itens em ordem, como quando cada etapa depende da anterior. Nesse caso, use um loop for...of com await em vez de forEach (que não espera por callbacks assíncronos).

for (const item of items) {
  await processItem(item);
}

Se você precisar limitar a concorrência, considere bibliotecas como p-limit ou implemente uma fila simples.

5. Evitando a armadilha do async/await em loops

Usar await dentro de Array.prototype.forEach é um erro clássico: forEach não aguarda o callback assíncrono, então o loop termina antes que as promises sejam resolvidas. Sempre use for...of ou map com Promise.all.

6. Async/await com timeouts

Para evitar requisições travadas, você pode competir uma promise contra um timeout.

function timeout(ms) {
  return new Promise((_, reject) =>
    setTimeout(() => reject(new Error('Timeout')), ms)
  );
}

await Promise.race([fetchData(), timeout(5000)]);

Este padrão é útil para chamadas de API que podem travar.

7. Geradores assíncronos e for await...of

Geradores assíncronos permitem produzir um fluxo de valores de forma assíncrona. Você pode consumi-los com for await...of.

async function* fetchPages() {
  let page = 1;
  while (true) {
    const data = await fetch(`/api/items?page=${page}`);
    if (data.length === 0) break;
    yield data;
    page++;
  }
}

for await (const page of fetchPages()) {
  console.log(page);
}

Isso é ótimo para APIs paginadas ou streaming de dados.

8. Erros comuns e como evitá-los

9. Boas práticas para código assíncrono limpo

FAQ

Qual é a diferença entre async/await e Promises?

Async/await é açúcar sintático sobre Promises, fazendo o código assíncrono parecer síncrono. Ele simplifica o encadeamento e o tratamento de erros com try/catch.

Posso usar await dentro de um loop forEach?

Não, o forEach não espera por callbacks assíncronos. Use for...of ou Promise.all com map.

Como executo várias operações assíncronas em paralelo?

Use Promise.all() para executá-las simultaneamente e esperar que todas sejam resolvidas.

Ao trabalhar com APIs JSON, você pode formatar e validar respostas rapidamente usando nosso JSON Formatter.