C'est une question plus ancienne mais j'essayais de faire quelque chose de similaire. J'ai besoin de garder n travailleurs. Ils sont structurés dans une promesse. Je dois scanner et voir s'ils sont résolus, rejetés ou toujours en attente. Si résolu, j'ai besoin de la valeur, si rejeté, faites quelque chose pour corriger le problème ou en attente. En cas de résolution ou de rejet, je dois commencer une autre tâche pour continuer. Je ne peux pas trouver un moyen de le faire avec Promise.all ou Promise.race car je continue à travailler les promesses dans un tableau et ne trouve aucun moyen de les supprimer. Alors je crée un ouvrier qui fait l'affaire
J'ai besoin d'une fonction de générateur de promesse qui renvoie une promesse qui résout ou rejette si nécessaire. Il est appelé par une fonction qui met en place le cadre pour savoir ce que fait la promesse.
Dans le code ci-dessous, le générateur renvoie simplement une promesse basée sur setTimeout.
C'est ici
//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 renvoie un objet contenant la promesse, son état et sa valeur retournée.
Le code suivant exécute une boucle qui teste l'état et crée de nouveaux nœuds de calcul pour le maintenir à 3 nœuds de calcul en cours d'exécution.
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();
Testé dans node.js
BTW Pas tellement dans cette réponse, mais dans d'autres sur des sujets similaires, je déteste quand quelqu'un dit «vous ne comprenez pas» ou «ce n'est pas comme ça que ça marche». Je suppose généralement que le questionneur sait ce qu'il veut. Suggérer une meilleure façon, c'est super. Une explication patiente du fonctionnement des promesses serait également une bonne chose.