// Tempo limite e cancelamento com os dois clientes, contra o servidor lento. // Em outro terminal, antes: npm run servidor-lento import axios, { isAxiosError, isCancel } from 'axios'; import { descrever, ms } from './api.js'; const LENTO = process.env.LENTO_URL ?? 'http://localhost:3100'; const esperar = (t: number) => new Promise((r) => setTimeout(r, t)); // 1. Sem limite nenhum: o fetch espera o que for preciso. let inicio = performance.now(); const semLimite = await fetch(`${LENTO}/ficha?atraso=1500`); console.log(`${ms(inicio)} fetch sem limite → ${semLimite.status}`); // 2. fetch com AbortSignal.timeout: desiste e fecha a conexão. inicio = performance.now(); try { await fetch(`${LENTO}/ficha?atraso=2000`, { signal: AbortSignal.timeout(500) }); } catch (erro) { console.log(`${ms(inicio)} fetch + timeout(500) → ${descrever(erro)}`); } // 3. axios com a opção `timeout`. inicio = performance.now(); try { await axios.get(`${LENTO}/ficha`, { params: { atraso: 2000 }, timeout: 500 }); } catch (erro) { if (!isAxiosError(erro)) throw erro; console.log(`${ms(inicio)} axios timeout: 500 → ${erro.code} · ${erro.message}`); } // 4. Cancelamento por decisão do programa (o usuário saiu da tela, digitou // outra letra): o mesmo AbortController serve aos dois clientes. const controle = new AbortController(); setTimeout(() => controle.abort(), 300); inicio = performance.now(); const resultados = await Promise.allSettled([ fetch(`${LENTO}/ficha?atraso=2000`, { signal: controle.signal }), axios.get(`${LENTO}/ficha`, { params: { atraso: 2000 }, signal: controle.signal }), ]); const [pelofetch, peloaxios] = resultados; if (pelofetch.status === 'rejected') { console.log(`${ms(inicio)} fetch abort() → ${descrever(pelofetch.reason)}`); } if (peloaxios.status === 'rejected') { const erro: unknown = peloaxios.reason; console.log( `${ms(inicio)} axios abort() → isCancel = ${isCancel(erro)} · ${isAxiosError(erro) ? erro.code : '?'}`, ); } // 5. Contraste com a Extra A: Promise.race só desiste de ESPERAR. O pedido // continua aberto, e o servidor responde como se nada tivesse acontecido. inicio = performance.now(); const estouro = new Promise((_, rejeitar) => setTimeout(() => rejeitar(new Error('tempo esgotado')), 500), ); try { await Promise.race([fetch(`${LENTO}/ficha?atraso=1000`), estouro]); } catch (erro) { console.log(`${ms(inicio)} Promise.race(500) → ${descrever(erro)} (o pedido segue aberto)`); } await esperar(700); // tempo para o servidor registrar a resposta que ninguém lê