
Na 71.ª reunião do Ecma TC39, serão considerados o projeto e a implementação de referência do Promise.allSettled
, o terceiro dos quatro principais combinadores de promessas.
Autores : Jason Williams (BBC), Robert Pumley (Bloomberg), Matthias Binens (Google)
Campeão : Matthias Binens (Google)
Etapa : 3
Para os fãs de podcasts, duplicados no YouTube .
Introdução e Motivação
Existem quatro principais combinadores no mundo das promessas:
Promise.all
. ES2015. Fecha na primeira promessa rejeitada / rejeitada.Promise.race
. ES2015. Fecha na primeira promessa de alguma forma resolvida / estabelecida.Promise.any
. Etapa 1. Fecha na primeira promessa satisfeita / cumprida.Promise.allSettled
. Etapa 3 → Etapa 4. Não fecha.
Todos eles são amplamente representados em bibliotecas de usuários comuns, cada um deles é útil por si só e adequado em várias situações.
A principal aplicação desse combinador ocorre quando você deseja executar uma ação imediatamente após a conclusão de muitos pedidos, independentemente de terem terminado com êxito ou falha. O restante dos combinadores de promessas são fechados ( curto-circuito ), descartando os resultados dos valores de entrada que perderam a corrida por um determinado estado do sistema. Promise.allSettled
é único, pois sempre espera todos por quem é responsável.
Promise.allSettled
retorna uma promessa, que é executada com o retorno de uma matriz de instantâneos dos estados das promessas, mas somente após absolutamente todas as promessas originais serem resolvidas.
De onde vem o nome allSettled?
Dizemos que uma promessa é liquidada ( liquidada ) se não for suspensa pendente , ou seja, quando ele está satisfeito ou rejeitado - uma das duas coisas. Para entender a terminologia, dê uma olhada no antigo documento States and Fates .
E também, esse nome, allSettled
, é amplamente usado em bibliotecas existentes que implementam essa funcionalidade. A lista estará abaixo.
Exemplos
Imagine que você precisa repetir uma série de promessas e retornar um novo valor com um status conhecido (que ocorre em qualquer um dos dois ramos possíveis da lógica).
function reflect(promise) { return promise.then( (v) => { return { status: 'fulfilled', value: v }; }, (error) => { return { status: 'rejected', reason: error }; } ); } const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ]; const results = await Promise.all(promises.map(reflect)); const successfulPromises = results.filter(p => p.status === 'fulfilled');
A API proposta permite que o desenvolvedor processe essas opções, sem a necessidade de criar a função reflect
independentemente ou armazenar os resultados em variáveis temporárias. A nova API fica assim:
const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ]; const results = await Promise.allSettled(promises); const successfulPromises = results.filter(p => p.status === 'fulfilled');
Se, por algum motivo, precisamos de promessas rejeitadas, provavelmente precisamos coletar os motivos do que aconteceu. allSettled
torna isso tão fácil.
const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ]; const results = await Promise.allSettled(promises); const errors = results .filter(p => p.status === 'rejected') .map(p => p.reason);
Exemplos reais
Muito comum é o desejo de saber que todas as solicitações foram concluídas, independentemente do status de cada uma delas. Isso é importante quando você deseja fazer melhorias graduais no futuro. Nem sempre precisamos obter uma resposta da API.
const urls = [ ]; const requests = urls.map(x => fetch(x));
Usando Promise.allSettled
você pode escrever algo que esteja mais de acordo com nossas expectativas.
Implementações personalizadas
Em outros idiomas
Funcionalidade semelhante existe em outros idiomas, sob nomes diferentes. Como não há mecanismo universal que seja imediatamente compatível com muitos idiomas, este documento segue o exemplo dos nomes das bibliotecas listadas acima. Veja como fica em outros idiomas:
- Ferrugem -
futures::join
; Task.WhenAll
. Você pode usar try / catch ou TaskContinuationOptions.OnlyOnFaulted
;- Python -
asyncio.wait
com a opção ALL_COMPLETED
- Java -
CompletableFuture.allOf
Materiais para estudos adicionais
Ata das reuniões do TC39
Especificação
Implementações