Promise.withResolvers()

Como o método Promise.withResolvers() do ECMAScript 2024 devolve a Promise junto com suas funções resolve e reject, eliminando o padrão verboso de declarar variáveis fora do construtor.

Toda vez que você precisa resolver ou rejeitar uma Promise a partir de um código que está fora do callback do construtor, acaba caindo no mesmo truque: declarar variáveis soltas e atribuí-las lá dentro. O método estático Promise.withResolvers() resolve esse incômodo devolvendo, de uma só vez, a Promise e as suas funções resolve e reject.

O jeito antigo

let resolve, reject;

const promessa = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
});

// Em algum outro lugar, mais tarde:
resolve('pronto!');

Funciona, mas é verboso: são três declarações só para conseguir "escapar" o resolve e o reject para fora do escopo do construtor.

Como funciona o withResolvers

O método devolve um objeto simples com três propriedades: a própria promise, e as funções resolve e reject já prontas para serem chamadas quando você quiser.

const { promise, resolve, reject } = Promise.withResolvers();

// Em algum outro lugar, mais tarde:
resolve('pronto!');

promise.then(valor => console.log(valor)); // "pronto!"

Com uma única linha e desestruturação você tem tudo o que antes exigia o bloco com let. Nada de variáveis soltas e sem valor inicial.

Exemplo prático: esperar um evento

Um caso clássico é transformar um evento único (como um clique) em algo que você possa await. Fica bem mais limpo:

function esperarClique(botao) {
    const { promise, resolve } = Promise.withResolvers();
    botao.addEventListener('click', resolve, { once: true });
    return promise;
}

const evento = await esperarClique(document.querySelector('#confirmar'));
console.log('Usuário confirmou!', evento);

Exemplo prático: fila de tarefas

Quando o resolve precisa ser guardado para ser chamado por outra parte do sistema, o padrão brilha. Aqui, cada tarefa enfileirada vira uma Promise cujo controle fica com o processador:

const fila = [];

function enfileirar(tarefa) {
    const { promise, resolve, reject } = Promise.withResolvers();
    fila.push({ tarefa, resolve, reject });
    return promise;
}

async function processar() {
    while (fila.length) {
        const { tarefa, resolve, reject } = fila.shift();
        try {
            resolve(await tarefa());
        } catch (erro) {
            reject(erro);
        }
    }
}

Quem chama enfileirar() recebe uma Promise e simplesmente aguarda; o processar() decide quando cada uma é resolvida ou rejeitada.

Quando usar

Detalhes de comportamento

As funções resolve e reject retornadas são exatamente as mesmas que o construtor entregaria: chamadas depois que a Promise já foi resolvida ou rejeitada simplesmente não têm efeito. Além disso, o objeto retornado é um objeto comum, então a desestruturação é a forma mais prática de usá-lo, mas você também pode guardá-lo inteiro em uma variável se preferir.

Compatibilidade

O Promise.withResolvers() faz parte do ECMAScript 2024 e já atingiu o status Baseline, com suporte nos navegadores modernos e no Node.js recente. Ainda assim, vale conferir antes de usar em produção se o projeto precisar suportar ambientes mais antigos.

caniuse

Conclusão

O Promise.withResolvers() elimina um padrão repetitivo e um pouco desajeitado que acompanhava o JavaScript há anos, deixando explícito e enxuto o caso em que o controle de resolução da Promise precisa viver fora do seu construtor.

Tecnologia:
js

Deixe seu Comentário!

Comentário
Nome
Email