voltar aos artigosasync javascript
$cd~/artigos/async-await-javascript-codigo-sincrono
Async JavaScript
série 33 Conceitos JS·parte 23 de 38

Async/Await: Escrevendo Código Assíncrono que Parece Síncrono

20 minVanderlei José Alamino

Por que código assíncrono parece complicado? E se buscar dados, esperar input ou ler arquivos lesse tão limpo quanto código síncrono?

A resposta é async/await — açúcar sintático do ES2017 sobre Promises. O JavaScript parece síncrono, mas continua não bloqueante por baixo.

snippetJavaScript
async function buscarPostsUsuario(userId) {  const usuario = await buscarUsuario(userId);  const posts = await buscarPosts(usuario.id);  const comentarios = await buscarComentarios(posts[0].id);  return { usuario, posts, comentarios };}

Neste guia da série 33 Conceitos JS — projeto open source criado por Leonardo Maldonado — você vai aprender:

  • O que async e await realmente fazem
  • try/catch para erros assíncronos
  • Sequencial vs paralelo com Promise.all
  • Erros comuns e relação com microtasks

Pré-requisitos: Promises e Event Loop.

async-await-javascript-codigo-sincrono.meta.jsonjson

// metadados do artigo

{
  "tag": "async javascript",
  "readTime": "20 min",
  "author": "Vanderlei José Alamino",
  "source": "33jsconcepts.com",
  "series": "33 Conceitos JS",
  "part": {
    "current": 23,
    "total": 38
  }
}
abrir fonte original
async-await-javascript-codigo-sincrono.mdmarkdown

Fonte de referência

Conteúdo adaptado a partir do guia original em inglês.

33jsconcepts.com
01

seção

O que é Async/Await?

async/await é forma amigável de escrever Promises — código assíncrono que lê como síncrono.

snippetJavaScript
// Callbacks — pirâmidebuscarUsuario(id, (err, u) => {  buscarPosts(u.id, (err, p) => { /* ... */ });}); // Promises — encadeamentoreturn buscarUsuario(id).then(u => buscarPosts(u.id)); // async/await — linearasync function buscar(id) {  const u = await buscarUsuario(id);  return await buscarPosts(u.id);}

Não substitui Promises — toda função async retorna Promise; await funciona com qualquer Promise.

02

seção

Analogia: Restaurante com Serviço de Mesa

Callbacks: você espera no balcão bloqueando a fila.

async/await: você senta, pede (await), conversa enquanto a cozinha trabalha — thread principal livre. Quando a comida chega, retoma de onde parou.

snippettext
await pedido()  →  cozinha prepara (async)                  →  você faz outras coisas                  →  garçom traz (Promise resolved)                  →  código continua após await
03

seção

A Palavra-Chave async

async faz a função retornar Promise:

snippetJavaScript
async function saudar() { return "Olá"; }console.log(saudar());  // Promise {<fulfilled>: "Olá"} async function falhar() { throw new Error("Ops!"); }// equivale a Promise.reject

Retornar Promise não envolve duas vezes:

snippetJavaScript
async function buscar() {  return fetch("/api/dados");  // Promise<Response>, não Promise<Promise>}

Funciona em arrow functions, métodos de objeto e classes:

snippetJavaScript
const load = async () => fetch("/api");const api = { async get(id) { return fetch(`/api/${id}`); } };

async não cria thread separada — só habilita await e garante retorno Promise.

04

seção

A Palavra-Chave await

await pausa a função async até a Promise settled, depois retoma com o valor:

snippetJavaScript
async function exemplo() {  console.log("Antes");  const r = await algumaPromise();  console.log("Depois", r);}

Só em função async ou top-level await (módulos ES).

snippetJavaScript
// ❌ em função regularfunction f() { await fetch(); }  // SyntaxError

await pausa a função, não a thread:

snippetJavaScript
async function lenta() {  console.log("Início");  await delay(2000);  console.log("Fim");}lenta();console.log("Depois");// Início → Depois → (2s) Fim
05

seção

Por Baixo dos Panos

Código após await vira microtarefa:

snippetJavaScript
async function exemplo() {  console.log("1");  await Promise.resolve();  console.log("2");}console.log("A");exemplo();console.log("B");// A, 1, B, 2
snippettext
await divide a função:  antes do await → síncrono  depois do await  → microtarefa (como .then())

Por isso microtasks (await, .then()) rodam antes de setTimeout. Veja Event Loop.

06

seção

Tratamento de Erros com try/catch

snippetJavaScript
async function buscarUsuario(id) {  try {    const res = await fetch(`/api/usuarios/${id}`);    if (!res.ok) throw new Error(`HTTP ${res.status}`);    return await res.json();  } catch (erro) {    console.error("Falha:", erro.message);    throw erro;  } finally {    esconderSpinner();  }}

Erro engolido — catch sem re-lançar resolve com undefined:

snippetJavaScript
// ❌try { return await fetch(url); }catch (e) { console.log(e); }  // undefined! // ✅catch (e) { console.log(e); throw e; }

.catch() pontual para fallback em uma operação:

snippetJavaScript
const posts = await buscarPosts(id).catch(() => []);
07

seção

Sequencial vs Paralelo

Sequencial (lento) — cada await espera o anterior:

snippetJavaScript
// ~1500msconst u = await buscarUsuario(id);const p = await buscarPosts(id);const n = await buscarNotificacoes(id);

Paralelo (rápido) — operações independentes:

snippetJavaScript
// ~500msconst [u, p, n] = await Promise.all([  buscarUsuario(id),  buscarPosts(id),  buscarNotificacoes(id),]);
SequencialParalelo
Cada passo depende do anteriorOperações independentes
Ordem importaOrdem não importa

Misto: pedido primeiro, depois inventário + preço em paralelo:

snippetJavaScript
const pedido = await buscarPedido(id);const [inv, preco] = await Promise.all([  verificarInventario(pedido.itens),  calcularPreco(pedido.itens),]);

Promise.allSettled quando sucesso parcial é OK — ver Promises.

08

seção

Os 5 Erros Mais Comuns

1. Esquecer await

snippetJavaScript
const res = fetch(url);  // Promise, não Response!

2. await em forEach

snippetJavaScript
// ❌ dispara e esqueceids.forEach(async id => await buscar(id));// ✅ for...of (sequencial) ou Promise.all + map (paralelo)

3. Sequencial quando poderia ser paralelo

Use Promise.all para independentes.

4. Sem tratamento de erro

try/catch ou .catch() no chamador.

5. return sem await em try/catch

snippetJavaScript
// ❌ catch não vê erro de fetchtry { return fetch(url); } catch (e) {} // ✅try { return await fetch(url); } catch (e) {}

Fora de try/catch, return await x e return x são equivalentes.

09

seção

Async/Await vs Cadeias de Promise

Aspectoasync/await.then()
LegibilidadeCódigo linearEncadeamento
Errostry/catch.catch()
Condicionaisif/else naturalaninhamento
Loopsfor...ofreduce/recursão

Promises puras ainda brilham em transformações curtas:

snippetJavaScript
buscarUsuario(id).then(u => u.profileId).then(buscarPerfil);

async/await em lógica condicional, loops e retry com backoff.

10

seção

Top-Level Await e Padrões Avançados

Top-level await — só em módulos ES:

snippetJavaScript
export const config = await fetch("/config.json").then(r => r.json());

Bloqueia carregamento do módulo e importadores — use com moderação.

Retry com backoff, timeout com Promise.race, AbortController para cancelar fetch.

for await...of — consumir iteradores async (preview de Generators na trilha).

Promisify callbacks → async/await (Node: util.promisify).

11

seção

Perguntas Clássicas de Entrevista

12

seção

Teste Seu Conhecimento

$ summary --quick

Resumo rápido

  • async/await = açúcar sobre Promises — não muda o modelo assíncrono
  • Função async sempre retorna Promise — valores envolvidos em Promise.resolve()
  • await pausa a função, não a thread — UI e event loop continuam
  • Após await = microtarefa — roda antes de setTimeout
  • try/catch — tratamento de erro familiar; cuidado com erro engolido
  • forEach + await não espera — use for...of ou Promise.all
  • Paralelo com Promise.all quando operações são independentes
  • Não esqueça await — senão você manipula Promise, não o valor
  • return await em try/catch — necessário para catch ver rejeições
  • Top-level await — só módulos ES; bloqueia imports dependentes

Créditos da série

Este artigo faz parte de uma série de estudos inspirada no projeto 33 Conceitos JS, criado por Leonardo Maldonado. Todo o conteúdo original está disponível em 33jsconcepts.com.