import { mensagemDeErro } from './biblioteca.js'; /** * Parte 9 — Quatro armadilhas, com a correção ao lado. * * npx tsx src/10-armadilhas.ts * * Os três primeiros padrões podem falhar; o quarto pode indicar uma * expectativa incorreta sobre a operação aguardada. */ import { buscarLivro, cronometro, esperar, salvarEmprestimo } from './biblioteca.js'; // A rejeição sem tratador derruba o processo do Node. O ouvinte abaixo existe // só para que a armadilha 3 possa ser demonstrada sem encerrar o programa. process.on('unhandledRejection', (motivo) => { console.log(` [unhandledRejection] ${mensagemDeErro(motivo)}`); }); // --------------------------------------------------------------------------- // 1. `forEach` com callback async: o laço termina antes do trabalho. // --------------------------------------------------------------------------- async function armadilhaForEach(): Promise { const marcar = cronometro(); const titulos: string[] = []; [1, 2, 3].forEach(async (id) => { const livro = await buscarLivro(id); titulos.push(livro.titulo); }); marcar(`forEach : ${titulos.length} títulos — o vetor ainda está vazio`); // Correção: `map` devolve as promises, e `Promise.all` espera por elas. const certos = await Promise.all([1, 2, 3].map(async (id) => (await buscarLivro(id)).titulo)); marcar(`map/all : ${certos.length} títulos`); } // --------------------------------------------------------------------------- // 2. `try`/`catch` sem `await`: o bloco já saiu quando o erro chega. // --------------------------------------------------------------------------- async function armadilhaTryCatch(): Promise { const marcar = cronometro(); try { // Sem `await`, o try apenas cria a promise e termina. A rejeição acontece // 300 ms depois, quando não há mais nenhum catch escutando. void buscarLivro(99).catch(() => { marcar('try/catch : a rejeição chegou fora do try — tratada aqui, não lá'); }); } catch { marcar('este catch NUNCA roda'); } // Correção: com `await`, a rejeição vira exceção dentro do bloco. try { await buscarLivro(99); } catch (erro) { marcar(`com await : ${(erro instanceof Error ? erro.name : 'erro desconhecido')} capturado no try`); } } // --------------------------------------------------------------------------- // 3. Promise solta: ninguém observa, ninguém trata. // --------------------------------------------------------------------------- function armadilhaPromiseSolta(): void { // Errado: dispara e esquece. Se rejeitar, ninguém trata — e o ouvinte lá em // cima é a única razão de este programa não morrer aqui. salvarEmprestimo(404, 'ana'); // Certo: ou `await`, ou um `catch` explícito com `void` declarando a // intenção de não esperar. void salvarEmprestimo(404, 'bruno').catch((erro: unknown) => { console.log(` [tratada] ${mensagemDeErro(erro)}`); }); } // --------------------------------------------------------------------------- // 4. `await` de coisa que não é promise: espera desperdiçada. // --------------------------------------------------------------------------- async function armadilhaAwaitInutil(): Promise { const marcar = cronometro(); const numero = await 42; // legal, mas adia a linha seguinte por uma microtask marcar(`await 42 : ${numero} — continuação agendada como microtask`); } async function principal(): Promise { await armadilhaForEach(); await armadilhaTryCatch(); armadilhaPromiseSolta(); await armadilhaAwaitInutil(); await esperar(400); // dá tempo de as promises soltas se manifestarem } void principal();