Questa è una domanda più vecchia, ma stavo cercando di fare qualcosa di simile. Devo far andare avanti n lavoratori. Sono strutturati in una promessa. Devo scansionare e vedere se sono stati risolti, rifiutati o ancora in sospeso. Se risolto, ho bisogno del valore, se rifiutato fare qualcosa per correggere il problema o in sospeso. Se risolto o rifiutato, devo avviare un'altra attività per continuare. Non riesco a immaginare un modo per farlo con Promise.all o Promise.race poiché continuo a mantenere le promesse in un array e non riesco a trovare alcun modo per eliminarle. Quindi creo un lavoratore che fa il trucco
Ho bisogno di una funzione di generatore di promesse che restituisce una promessa che si risolve o rifiuta, se necessario. Viene chiamato da una funzione che imposta il framework per sapere cosa sta facendo la promessa.
Nel codice sottostante il generatore restituisce semplicemente una promessa basata su setTimeout.
Ecco qui
//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 restituisce un oggetto contenente la promessa, il suo stato e il valore restituito.
Il codice seguente esegue un ciclo che verifica lo stato e crea nuovi lavoratori per mantenerlo su 3 lavoratori in esecuzione.
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();
Testato in node.js
A proposito non in questa risposta così tanto, ma in altri su argomenti simili, lo odio quando qualcuno dice "non capisci" o "non è così che funziona" In genere suppongo che l'interrogante sappia cosa vogliono. Suggerire un modo migliore è fantastico. Sarebbe anche utile una spiegazione paziente di come funzionano le promesse.