Ententendo a API de Promises e suas novidades
Desde a introdução de Promises no ES2015, o JavaScript suportou exatamente dois combinadores: os métodos estáticos Promise.all
e Promise.race
.
Duas novas propostas estão atualmente passando pelo processo de padronização: Promise.allSettled
e Promise.any
. Com essas adições, haverá um total de quatro combinadores de Promises em JavaScript, cada um permitindo diferentes casos de uso.
Aqui está uma visão geral dos quatro combinadores:
- Promise.allSettled: não há curto-circuito, em proposta
- Promise.all: curto-circuito quando um valor de entrada é rejeitado, adicionado no ES2015 ✅
- Promise.race: curto-circuito quando algum valor de entrada for decidido (rejeitado ou resolvido), adicionado no ES2015 ✅
- Promise.any: curto-circuito quando um valor de entrada for resolvido, em proposta
Vamos dar uma olhada em um exemplo de caso de uso para cada combinador.
Promise.all
Veja o suporte em https://v8.dev/features/support
Promise.all
permite que você saiba quando todas as promessas de entrada foram cumpridas ou quando uma delas foi rejeitada.
Imagine que o usuário clica em um botão e deseja carregar algumas folhas de estilo para que você possa renderizar uma interface de usuário completamente nova. Este programa inicia uma solicitação HTTP para cada folha de estilo em paralelo:
const promises = [
fetch('/component-a.css'),
fetch('/component-b.css'),
fetch('/component-c.css'),
];
try {
const styleResponses = await Promise.all(promises);
enableStyles(styleResponses);
renderNewUi();
} catch (reason) {
displayError(reason);
}
Você só deseja começar a renderizar a nova interface de usuário depois que todas as solicitações forem bem-sucedidas. Se algo der errado, você deseja exibir uma mensagem de erro o mais rápido possível, sem esperar que outro trabalho acabe.
Nesse caso, você poderia usar Promise.all
: você quer saber quando todas as promessas são cumpridas ou assim que uma delas é rejeitada.
Promise.race
Veja o suporte em https://v8.dev/features/support
Promise.race
é útil se você deseja executar várias promessas e também:
- fazer algo com o primeiro resultado bem-sucedido que chegar (no caso de uma das promessas ser cumprida), ou
- faça algo assim que uma das promessas for rejeitada.
Isto é, se uma das promessas for rejeitada, você quer preservar essa rejeição para tratar o caso de erro separadamente. O exemplo a seguir faz exatamente isso:
try {
const result = await Promise.race([
performHeavyComputation(),
rejectAfterTimeout(2000),
]);
renderResult(result);
} catch (error) {
renderError(error);
}
Iniciamos uma tarefa computacionalmente pesada que pode levar muito tempo, mas corremos contra uma promessa que rejeita após 2 segundos. Dependendo da primeira promessa a ser cumprida ou rejeitada, renderizamos o resultado computado ou a mensagem de erro em dois caminhos de código separados.
Promise.allSettled
Veja o suporte em https://v8.dev/features/support
Promise.allSettled
te dá um sinal quando todas as promessas de entrada são decididas, o que significa que elas são resolvidas ou rejeitadas. Isso é útil nos casos em que você não se importa com o estado das promessas, você só quer saber quando o trabalho está concluído, independentemente de ter sido bem-sucedido.
Por exemplo, você pode dar início a uma série de chamadas de API independentes e usa Promise.allSettled
para garantir que todas sejam concluídas antes de fazer outra coisa, como remover um controle giratório de carregamento:
const promises = [
fetch('/api-call-1'),
fetch('/api-call-2'),
fetch('/api-call-3'),
];
// Imagine que algumas dessas requisições falhem e outras são bem-sucedidas
await Promise.allSettled(promises);
// Todas as chamadas de API foram finalizadas (falhas e sucessos)
removeLoadingIndicator();
Promise.any
Veja o suporte em https://v8.dev/features/support
Promise.any
te dá um sinal assim que uma das promessas se cumprem. Isso é semelhante a Promise.race
, exceto que any
não rejeita cedo quando uma das promessas é rejeitada.
const promises = [
fetch('/endpoint-a').then(() => 'a'),
fetch('/endpoint-b').then(() => 'b'),
fetch('/endpoint-c').then(() => 'c'),
];
try {
const first = await Promise.any(promises);
// Qualquer uma das promessas foi cumprida.
// → e.g. 'b'
console.log(first);
} catch (error) {
// Todas as promessas foram rejeitadas.
console.log(error);
}
Este exemplo de código verifica qual endpoint responde o mais rápido e faz o log dele. Somente se todos os pedidos falharem, acabaremos no bloco catch
, onde poderemos lidar com os erros.
Créditos ⭐️
- Promise combinators, escrito originalmente por Mathias Bynens
Top comments (0)