La función de Javascript Promise.allSettled espera a que finalicen todas las promesas resueltas o rechazadas. Promise.all no devolverá las promesas resueltas si alguna de ellas es rechazada, y Promise.race y Promise.any solo dan la primera promesa resuelta o cumplida.
¿Hay alguna manera de enviar múltiples promesas (digamos 100) y luego, tan pronto como una falle (quizás tener 20 exitosas) cancelar las promesas no resueltas (de las cuales hay 100 - 20 - 1 = 79 aún no resueltas)? Ni siquiera necesito los detalles de cuál falló, sino solo una especie de función Promise.someSettled.
Para el contexto, estoy mapeando entre datos y llamadas de búsqueda, y me gustaría saber qué búsquedas deben volver a intentarse.
¿Es eso posible?
Debido a que las promesas de entrada y los valores de resolución de salida no son uno a uno, creo que la forma más fácil de administrar esto sería simplemente empujar a una matriz externa en la resolución y usar Promise.all para esperar un rechazo, algo así como :
const makePromises = () => Array.from( { length: 100 }, (_, i) => new Promise((resolve, reject) => { setTimeout(() => { if (Math.random() > 0.05) resolve(i); else reject(); }, 1000 * Math.random()); }) ); const resolveValues = []; Promise.all( makePromises() .map(prom => prom.then(val => { resolveValues.push(val); })) ) .then(() => { console.log('Unexpected - All promises resolved'); }) .catch(() => { const innerResolveValues = [...resolveValues]; console.log('Done:'); console.log(innerResolveValues); });Parece que está tratando de crear un indicador de progreso para una gran cantidad de llamadas.
Una solución simple sería dividir la gran cantidad de llamadas en grupos más pequeños y usar Promise.allSettled() para determinar cuándo finaliza cada grupo. Luego puede comparar la cantidad de grupos terminados con la cantidad de grupos sin terminar para obtener una medida del progreso.
¡Sí, @Certainperformance lo golpeó en la cabeza! Aquí hay otra forma de ensamblar la matriz de promesas, pero la idea es exactamente la misma:
for (var acc=[], pr=[], i=0; i<100; i++) pr.push(new Promise((rs,rj)=>setTimeout((i<20?rs:rj).bind(null,i),200*i)) .then(d=>{acc.push(d)})) Promise.all(pr).then( d=>{console.log("all done!", acc)}, e=>{console.log("with some errors:", acc)} ); .as-console-wrapper {max-height: 100% !important; top: 0; } En mi ejemplo, dejo que las primeras promesas de finalización tengan éxito y rechazo las posteriores (para i>=20 ). Las promesas terminan en una secuencia de 0.2s una tras otra. Entonces, después de 4,2 segundos, se devuelve la primera promesa rechazada y se ejecutará la rama "fallida" del .then() externo, enumerando las promesas exitosas acumuladas en acc .