Como Adicionar Timeout em Promises JavaScript com Promise.race
Requisições assíncronas sem tempo limite de resposta podem travar o fluxo da aplicação e deixar o usuário esperando indefinidamente. Encapsular qualquer Promise em uma função de timeout usando Promise.race() resolve esse problema, cancelando o fluxo lógico e lançando um erro caso a operação exceda o tempo máximo estipulado.
JavaScript
/**
* Adiciona um tempo limite máximo para a resolução de uma Promise.
* @param {Promise<any>} promessa - A Promise original a ser executada.
* @param {number} tempoMs - O tempo limite em milissegundos.
* @returns {Promise<any>} A promessa resolvida ou uma rejeição por timeout.
*/
function comTimeout(promessa, tempoMs) {
// Cria uma Promise que é rejeitada automaticamente após decorrido o tempo limite
const timeout = new Promise((_, reject) => {
setTimeout(() => {
reject(new Error(`A operação excedeu o tempo limite de ${tempoMs}ms.`));
}, tempoMs);
});
// Retorna a primeira Promise que for resolvida ou rejeitada
return Promise.race([promessa, timeout]);
}
// --- Exemplo Prático de Uso ---
// Simula uma requisição lenta que demora 3 segundos para responder
const requisicaoLenta = new Promise((resolve) => {
setTimeout(() => resolve('Dados recebidos do servidor!'), 3000);
});
// Tenta executar a requisição com um limite rigoroso de 1,5 segundos (1500ms)
comTimeout(requisicaoLenta, 1500)
.then((resultado) => console.log('Sucesso:', resultado))
.catch((erro) => console.error('Falha:', erro.message));
Pontos-chave
- Funcionamento do
Promise.race(): Executa as Promises concorrentemente e assume o resultado da primeira que for finalizada, descartando o retorno das demais. - Atenção a Side Effects: O
Promise.race()interrompe a espera na aplicação, mas não cancela a execução interna da Promise original (como umfetchem andamento); para cancelar requisições HTTP, utilizeAbortController. - Tratamento de Exceções: Lançar uma instância de
Errordentro da Promise de timeout permite capturar a falha de forma limpa em blocostry/catchou no.catch(). - Reutilização Universal: A função é genérica e aceita qualquer operação assíncrona baseada em Promises, como consultas a bancos de dados, chamadas de API ou leitura de arquivos.
