Esta es una pregunta anterior, pero estaba tratando de hacer algo similar. Necesito mantener a n trabajadores trabajando. Están estructurados en una promesa. Necesito escanear y ver si están resueltos, rechazados o aún pendientes. Si se resuelve, necesito el valor, si se rechaza hacer algo para corregir el problema o pendiente. Si se resuelve o rechaza, necesito comenzar otra tarea para continuar. No puedo encontrar una manera de hacerlo con Promise.all o Promise.race, ya que sigo trabajando las promesas en una matriz y no puedo encontrar la manera de eliminarlas. Entonces creo un trabajador que hace el truco
Necesito una función de generador de promesas que devuelva una promesa que se resuelva o rechace según sea necesario. Es invocado por una función que configura el marco para saber qué está haciendo la promesa.
En el siguiente código, el generador simplemente devuelve una promesa basada en setTimeout.
Aquí está
//argObj should be of form
// {succeed: <true or false, nTimer: <desired time out>}
function promiseGenerator(argsObj) {
let succeed = argsObj.succeed;
let nTimer = argsObj.nTimer;
return new Promise((resolve, reject) => {
setTimeout(() => {
if (succeed) {
resolve('ok');
}
else {
reject(`fail`);
}
}, nTimer);
})
}
function doWork(generatorargs) {
let sp = { state: `pending`, value: ``, promise: "" };
let p1 = promiseGenerator(generatorargs)
.then((value) => {
sp.state = "resolved";
sp.value = value;
})
.catch((err) => {
sp.state = "rejected";
sp.value = err;
})
sp.promise = p1;
return sp;
}
doWork devuelve un objeto que contiene la promesa y su estado y valor devuelto.
El siguiente código ejecuta un ciclo que prueba el estado y crea nuevos trabajadores para mantenerlo en 3 trabajadores en ejecución.
let promiseArray = [];
promiseArray.push(doWork({ succeed: true, nTimer: 1000 }));
promiseArray.push(doWork({ succeed: true, nTimer: 500 }));
promiseArray.push(doWork({ succeed: false, nTimer: 3000 }));
function loopTimerPromise(delay) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
}, delay)
})
}
async function looper() {
let nPromises = 3; //just for breaking loop
let nloop = 0; //just for breaking loop
let i;
//let continueLoop = true;
while (true) {
await loopTimerPromise(900); //execute loop every 900ms
nloop++;
//console.log(`promiseArray.length = ${promiseArray.length}`);
for (i = promiseArray.length; i--; i > -1) {
console.log(`index ${i} state: ${promiseArray[i].state}`);
switch (promiseArray[i].state) {
case "pending":
break;
case "resolved":
nPromises++;
promiseArray.splice(i, 1);
promiseArray.push(doWork({ succeed: true, nTimer: 1000 }));
break;
case "rejected":
//take recovery action
nPromises++;
promiseArray.splice(i, 1);
promiseArray.push(doWork({ succeed: false, nTimer: 500 }));
break;
default:
console.log(`error bad state in i=${i} state:${promiseArray[i].state} `)
break;
}
}
console.log(``);
if (nloop > 10 || nPromises > 10) {
//should do a Promise.all on remaining promises to clean them up but not for test
break;
}
}
}
looper();
Probado en node.js
Por cierto, no tanto en esta respuesta, sino en otros sobre temas similares, ODIO cuando alguien dice "no entiendes" o "no funciona así". Por lo general, supongo que el interlocutor sabe lo que quiere. Sugerir una mejor manera es genial. Una explicación paciente de cómo funcionan las promesas también sería buena.