Veo un montón de funciones prometedoras como aquí https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race
pero, ¿hay alguna función que pueda usar que sea similar a la función array.prototype.some? Algo como esto
var promises = [...]; // this is an array of promises var containsTrue = await Promise.some(promises, x => x);
Se resuelve como true
tan pronto como cualquiera de las promesas se resuelve como true
. Se resuelve como false
si todos se resuelven como false
.
Si alguna promesa rechaza, rechaza inmediatamente.
¿Alguien sabe la mejor manera de implementar esto?
Puede combinar Promise.any
con un controlador adicional que arroja si el valor no es verdadero (o verdadero, la lógica que necesite).
await Promise.any( promises.map(promise => promise.then( (result) => { if (!result) throw new Error(); // Make this reject } )) ); // will reject if all promises reject
Asumiendo que la especificación es esta:
true
tan pronto como alguna de las promesas se resuelva como true
.false
si todas las promesas se resuelven en false
. Entonces, no hay una función de promesa incorporada específica que haga eso. Ni Promise.race()
ni Promise.any()
coinciden perfectamente.
El problema con Promise.race()
y Promise.any()
es que ambos se resuelven tan pronto como se resuelve cualquier promesa que les hayas hecho. No buscan que el valor resuelto sea true
. Según su especificación, si una promesa se resuelve en false
, desea seguir esperando que otra posiblemente se resuelva en true
. Eso, por definición, no funcionará con Promise.race()
porque finaliza cada vez que la primera promesa se resuelve o rechaza, lo cual no es lo que desea.
Promise.any()
podría funcionar parcialmente al cambiar artificialmente una promesa que se resuelve como falsa en un rechazo temporal, pero de alguna manera realizar un seguimiento de si realmente se rechazó o si simplemente fingimos un rechazo para evitar que Promise.any()
finalice. Pero, no hay forma de decirle que se detenga inmediatamente cuando recibe un rechazo real porque su diseño es continuar hasta el final en busca de cualquier promesa que se resuelva, ignorando los rechazos a menos que todos rechacen.
Entonces, Promise.race()
se detiene demasiado rápido cuando quieres que siga buscando y Promise.any()
no se detiene rápidamente cuando quieres que lo haga.
Entonces, así es como puede crear su propia implementación:
function PromiseSome(iterable) { return new Promise((resolve, reject) => { let len = 0; let doneCnt = 0; for (let p of iterable) { ++len; Promise.resolve(p).then(result => { ++doneCnt; if (result === true) { resolve(true); } else { // if done with all of them if (doneCnt === len) { resolve(false); } } }).catch(reject); } }); }
O, si desea ignorar todos los rechazos (simplemente trátelos de la misma manera que si resolviera false
), puede hacer esto:
function PromiseSome(iterable) { return new Promise((resolve, reject) => { let len = 0; let doneCnt = 0; for (let p of iterable) { ++len; Promise.resolve(p).catch(err => { // treat any rejection as just resolving false return false; }).then(result => { ++doneCnt; if (result === true) { resolve(true); } else { // if done with all of them if (doneCnt === len) { resolve(false); } } }); } }); }
Tenga en cuenta que estos están diseñados para buscar el resultado EXACTO de true
. Si desea que coincida algún valor real, puede cambiar de if (result === true)
a if (result)
.