
En la 71ª reunión de Ecma TC39, se considerará el proyecto y la implementación de referencia de Promise.allSettled
, el tercero de los cuatro principales combinadores de promesas.
Autores : Jason Williams (BBC), Robert Pumley (Bloomberg), Matthias Binens (Google)
Campeón : Matthias Binens (Google)
Etapa : 3
Para los fanáticos de los podcasts, duplicados en YouTube .
Introducción y motivación
Hay cuatro combinadores principales en el mundo de las promesas:
Promise.all
. ES2015. Cierra en la primera promesa rechazada / rechazada.Promise.race
. ES2015. Cierra en la primera promesa resuelta / resuelta de alguna manera.Promise.any
. Promise.any
. Etapa 1. Cierra en la primera promesa satisfecha / cumplida.Promise.allSettled
. Etapa 3 → Etapa 4. No se cierra.
Todos ellos están ampliamente representados en las bibliotecas de usuarios comunes, cada uno de ellos es útil en sí mismo y es adecuado en diversas situaciones.
La aplicación principal de este combinador ocurre cuando desea realizar una acción inmediatamente después de completar muchas solicitudes, independientemente de si terminaron con éxito o fallaron. El resto de los combinadores de promesas están cerrados ( cortocircuito ), descartando los resultados de los valores de entrada que han perdido la carrera por un cierto estado del sistema. Promise.allSettled
es único en el sentido de que siempre espera a todos los responsables.
Promise.allSettled
devuelve una promesa, que se ejecuta con el retorno de una serie de instantáneas de los estados de las promesas, pero solo después de que se resuelvan absolutamente todas las promesas originales.
¿De dónde viene el nombre allSettled?
Decimos que una promesa se liquida ( liquida ) si no se suspende pendiente , es decir cuando está satisfecho o rechazado, una de dos cosas. Para comprender la terminología, eche un vistazo al antiguo documento de Estados y destinos .
Y también, este nombre, allSettled
, se usa ampliamente en las bibliotecas existentes que implementan esta funcionalidad. La lista estará debajo.
Ejemplos
Imagine que necesita iterar sobre una serie de promesas y devolver un nuevo valor con un estado conocido (que ocurre en cualquiera de las dos ramas posibles de la 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');
La API propuesta permite al desarrollador procesar estas opciones, sin la necesidad de crear la función de reflect
independiente, o almacenar los resultados en variables temporales. La nueva API se ve así:
const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ]; const results = await Promise.allSettled(promises); const successfulPromises = results.filter(p => p.status === 'fulfilled');
Si por alguna razón necesitamos promesas rechazadas, entonces probablemente necesitemos reunir las razones de lo que sucedió. allSettled
hace que esto sea igual de 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);
Ejemplos reales
Muy común es el deseo de saber que todas las solicitudes se han completado, independientemente del estado de cada una de ellas. Esto es importante cuando desea hacer una mejora gradual en el futuro. No siempre necesitamos obtener una respuesta de la API.
const urls = [ ]; const requests = urls.map(x => fetch(x));
Con Promise.allSettled
puede escribir algo más acorde con nuestras expectativas.
Implementaciones personalizadas
En otros idiomas
Funcionalidad similar existe en otros idiomas, bajo diferentes nombres. Dado que no existe un mecanismo universal que sea inmediatamente compatible con muchos idiomas, este documento sigue el ejemplo de los nombres de las bibliotecas enumeradas anteriormente. Así es como se ve en otros idiomas:
- Óxido -
futures::join
; - C # -
Task.WhenAll
. Task.WhenAll
. Puede usar try / catch o TaskContinuationOptions.OnlyOnFaulted
; - Python -
asyncio.wait
con la opción ALL_COMPLETED
- Java -
CompletableFuture.allOf
Materiales para ulterior estudio
Acta de las reuniones de TC39
Especificación
Implementaciones