Dies ist eine ältere Frage, aber ich habe versucht, etwas Ähnliches zu tun. Ich muss n Arbeiter am Laufen halten. Sie sind in einem Versprechen strukturiert. Ich muss scannen und sehen, ob sie gelöst, abgelehnt oder noch ausstehend sind. Wenn es behoben ist, brauche ich den Wert. Wenn es abgelehnt wird, kann das Problem behoben werden oder steht noch aus. Wenn gelöst oder abgelehnt, muss ich eine andere Aufgabe starten, um weiterzumachen. Ich kann mit Promise.all oder Promise.race keine Möglichkeit finden, dies zu tun, da ich weiterhin Versprechen in einem Array arbeite und keine Möglichkeit finde, sie zu löschen. Also erstelle ich einen Arbeiter, der den Trick macht
Ich benötige eine Versprechen-Generator-Funktion, die ein Versprechen zurückgibt, das bei Bedarf aufgelöst oder abgelehnt wird. Es wird von einer Funktion aufgerufen, die das Framework einrichtet, um zu wissen, was das Versprechen tut.
Im folgenden Code gibt der Generator einfach ein Versprechen zurück, das auf setTimeout basiert.
Hier ist es
//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 gibt ein Objekt zurück, das das Versprechen sowie dessen Status und Rückgabewert enthält.
Der folgende Code führt eine Schleife aus, die den Status testet und neue Worker erstellt, um ihn bei 3 laufenden Workern zu halten.
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();
Getestet in node.js
Übrigens Nicht in dieser Antwort, sondern in anderen zu ähnlichen Themen, ich hasse es, wenn jemand sagt "Sie verstehen nicht" oder "So funktioniert es nicht". Ich gehe im Allgemeinen davon aus, dass der Fragesteller weiß, was er will. Einen besseren Weg vorzuschlagen ist großartig. Eine geduldige Erklärung, wie Versprechen funktionieren, wäre auch gut.