programandoai

Erros assíncronos

Um try/catch comum não pega sozinho um erro que acontece dentro de uma Promise solta por aí. Só o await dentro de um try/catch, ou o .catch() explícito da Promise, cerca esse tipo de erro de verdade.

Estudar esta lição interativa →

No Módulo 8, você aprendeu que await pausa uma função async até uma tarefa demorada terminar. E se essa tarefa falhar, em vez de terminar bem? A boa notícia é que o padrão que você já usou no fetch (envolver o await num try/catch) continua funcionando exatamente como esperado: quando uma Promise é rejeitada (o nome técnico para "essa tarefa assíncrona deu errado"), o await a transforma num erro lançado ali mesmo, e o catch ao redor o pega, igualzinho a um erro síncrono comum.

function buscarUsuario(id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (id <= 0) reject(new Error("id inválido"));
      else resolve({ id, nome: "Usuário " + id });
    }, 10);
  });
}

async function carregarPerfil(id) {
  try {
    const usuario = await buscarUsuario(id); // await + try/catch cerca o erro
    console.log("Carregado:", usuario.nome);
  } catch (erro) {
    console.log("Falhou:", erro.message);
  }
}

carregarPerfil(1);   // Carregado: Usuário 1
carregarPerfil(-1);  // Falhou: id inválido

Existe também um jeito de tratar o erro sem async/await, direto na Promise, encadeando um .catch() depois do .then() (ou sozinho). Os dois estilos resolvem o mesmo problema; hoje em dia, async/await com try/catch costuma ser preferido por deixar o código com aparência mais linear e fácil de ler, mas reconhecer o .catch() é importante porque ele aparece bastante em código já existente por aí.

O perigo do await esquecido dentro do try

Um erro sutil: envolver a chamada de uma função async num try/catch, mas esquecer o await na frente dela. Sem await, a função assíncrona começa a rodar, mas o código não espera por ela, então, se ela falhar mais tarde, esse erro acontece depois que o bloco try já foi embora, e o catch nunca chega a vê-lo. O resultado costuma ser um aviso de "Uncaught (in promise)" no console, silencioso e fácil de passar batido. Regra de ouro: toda chamada a uma função async dentro de um try que você quer proteger precisa do await na frente.

Esse cuidado importa especialmente ao buscar dados de verdade: uma API pode estar fora do ar, a internet do usuário pode cair no meio do caminho, o servidor pode devolver algo inesperado. Um app que trata esses casos mostra uma mensagem amigável ("Não foi possível carregar, tente novamente"); um que não trata trava a tela ou, pior, mostra um erro técnico cru para quem só queria ver os dados.

// Sua vez! Complete carregarPerfil usando await dentro de um try/catch.
function buscarUsuario(id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (id <= 0) reject(new Error("id inválido"));
      else resolve({ id, nome: "Usuário " + id });
    }, 10);
  });
}

async function carregarPerfil(id) {
  // use await buscarUsuario(id) dentro de um try/catch
  // se der certo, retorne o resultado
  // se falhar, retorne "Erro ao carregar: " + erro.message
}

carregarPerfil(1).then((r) => console.log(r));
carregarPerfil(-1).then((r) => console.log(r));

Complete o tratamento de erro assíncrono e clique em Rodar.

← Voltar ao índice do curso