Async/await foi um divisor de águas no JavaScript. Mas com poder vem responsabilidade — é fácil cair em armadilhas de performance e legibilidade.

Sequential vs Parallel

// ❌ Lento: executa uma requisição depois da outra
const user = await fetchUser(id);
const posts = await fetchPosts(user.id);

// ✅ Rápido: paralelo quando não há dependência
const [user, posts] = await Promise.all([
  fetchUser(id),
  fetchPostsByUser(id),
]);

Error handling limpo

Evite try/catch gigantes:

function safeAsync(promise) {
  return promise.then(
    (data) => [null, data],
    (error) => [error, null]
  );
}

const [err, user] = await safeAsync(fetchUser(id));
if (err) return showError(err);

Timeout em promises

function withTimeout(promise, ms) {
  const timeout = new Promise((_, reject) =>
    setTimeout(() => reject(new Error("timeout")), ms)
  );
  return Promise.race([promise, timeout]);
}

Async/await não elimina a necessidade de pensar concorrência — só torna a sintaxe mais limpa. O reassignment loop (await dentro de for) ainda é sequencial.