Promise.try(): Unificando Código Síncrono e Assíncrono em uma Promise

Entenda como o Promise.try() captura erros síncronos que escapavam do Promise.resolve(), unificando funções síncronas e assíncronas em um único fluxo de tratamento de erros.

Misturar código síncrono e assíncrono dentro de uma Promise sempre teve uma armadilha: se a função passada para Promise.resolve() lançar um erro de forma síncrona, esse erro não vira uma rejeição — ele estoura direto, fora da cadeia de .then()/.catch(). O método estático Promise.try() resolve isso: ele executa a função imediatamente e garante que qualquer resultado, erro síncrono ou Promise rejeitada caia sempre no mesmo fluxo.

O problema que ele resolve

Uma forma comum de "elevar" uma função qualquer a uma Promise é envolver a chamada com Promise.resolve(). Só que isso não protege contra um throw síncrono:

function validar(valor) {
    if (!valor) throw new Error('valor inválido');
    return valor;
}

try {
    Promise.resolve(validar(null)).catch(erro => {
        console.log('capturado no catch:', erro.message);
    });
} catch (erro) {
    console.log('escapou para o try/catch síncrono:', erro.message);
    // "escapou para o try/catch síncrono: valor inválido"
}

O erro nunca chega ao .catch(), porque validar(null) já lança antes mesmo de Promise.resolve() ser chamado. Para evitar isso, era preciso recorrer a new Promise((resolve) => resolve(validar(valor))), que funciona mas é verboso.

Como funciona o Promise.try()

O método recebe uma função, executa-a de forma síncrona e devolve uma Promise: se ela retornar um valor, a Promise é cumprida com esse valor; se lançar um erro (síncrono ou assíncrono), a Promise é rejeitada:

function validar(valor) {
    if (!valor) throw new Error('valor inválido');
    return valor;
}

Promise.try(() => validar(null))
    .then(valor => console.log('ok:', valor))
    .catch(erro => console.log('capturado no catch:', erro.message));
// "capturado no catch: valor inválido"

Não importa se a função é síncrona, assíncrona, retorna um valor direto ou uma Promise — o resultado sempre passa pela mesma cadeia de .then()/.catch().

Funciona igual para funções síncronas e assíncronas

function calcularSincrono() {
    return 42;
}

async function calcularAssincrono() {
    await new Promise(r => setTimeout(r, 100));
    return 42;
}

// Ambas passam pelo mesmo tratamento:
Promise.try(calcularSincrono).then(v => console.log('síncrono:', v));
Promise.try(calcularAssincrono).then(v => console.log('assíncrono:', v));

Isso é útil quando uma API aceita um callback que o usuário pode implementar tanto de forma síncrona quanto assíncrona, e você não quer ter dois caminhos de tratamento de erro diferentes.

Argumentos extras sem criar closure

Promise.try() aceita argumentos adicionais e os repassa direto para a função, evitando a necessidade de uma arrow function só para isso:

function somar(a, b) {
    return a + b;
}

// Em vez de:
Promise.try(() => somar(2, 3));

// Pode ser:
Promise.try(somar, 2, 3).then(resultado => console.log(resultado)); // 5

Quando usar

Diferença para Promise.resolve()

Promise.resolve(func()) primeiro executa func() — e se essa chamada lançar, o erro nunca chega a virar argumento de Promise.resolve(). Já Promise.try(func) executa a função dentro de um contexto que já sabe capturar exceções síncronas, transformando-as em rejeição. É a mesma diferença que existe entre chamar uma função direto dentro de um try/catch e chamá-la dentro do executor de new Promise().

Compatibilidade

Promise.try() atingiu o status Baseline "newly available" no início de 2025, com suporte no Chrome, Firefox e Safari, além do Node.js recente. Por ser uma adição nova, vale confirmar o suporte antes de usar em produção caso o projeto precise rodar em navegadores mais antigos, ou usar um polyfill nesse caso.

caniuse

Conclusão

Promise.try() fecha uma lacuna que existia desde os primeiros dias das Promises: transformar qualquer chamada de função — síncrona, assíncrona, que lança erro ou que retorna Promise — em um único fluxo previsível, sem precisar recorrer ao construtor verboso de new Promise() só para capturar exceções síncronas.

Tecnologia:
js

Deixe seu Comentário!

Comentário
Nome
Email