Promise.withResolvers, ou a promessa com as rédeas de fora
Há um padrão que qualquer pessoa que trabalhe com promessas já escreveu: criar uma promessa e guardar o resolve numa variável de fora, para a resolver mais tarde, a partir de outro sítio do código.
Escrevia-se assim, e não era bonito:
let resolver;
let rejeitar;
const promessa = new Promise((resolve, reject) => {
resolver = resolve;
rejeitar = reject;
});O ECMAScript 2024 deu-lhe um nome. O Promise.withResolvers() devolve as três coisas de uma vez:
const { promise, resolve, reject } = Promise.withResolvers();1. Esperar por um evento, uma vez só
function esperarPorClique(botao) {
const { promise, resolve } = Promise.withResolvers();
botao.addEventListener('click', resolve, { once: true });
return promise;
}
await esperarPorClique(document.querySelector('#continuar'));
console.log('a pessoa carregou');2. Uma fila de pedidos com resposta diferida
O caso onde isto brilha mesmo é quando quem pergunta e quem responde estão em sítios diferentes do código — um worker, uma ligação WebSocket, uma mensagem entre janelas:
const pendentes = new Map();
let proximoId = 0;
function perguntarAoWorker(pergunta) {
const { promise, resolve } = Promise.withResolvers();
const id = proximoId++;
pendentes.set(id, resolve);
worker.postMessage({ id, pergunta });
return promise; // quem chamou espera aqui
}
worker.addEventListener('message', (evento) => {
const resolve = pendentes.get(evento.data.id);
pendentes.delete(evento.data.id);
resolve(evento.data.resposta); // e a espera acaba aqui
});Não faz nada que não se pudesse fazer antes. Poupa quatro linhas e, sobretudo, dá um nome a um padrão que toda a gente reinventava à sua maneira.