To jest starsze pytanie, ale próbowałem zrobić coś podobnego. Muszę podtrzymać pracę n pracowników. Są zorganizowane w obietnicę. Muszę zeskanować i sprawdzić, czy zostały rozwiązane, odrzucone lub nadal oczekują. Jeśli problem zostanie rozwiązany, potrzebuję wartości, a jeśli zostanie odrzucona, zrób coś, aby rozwiązać problem lub oczekuję. Jeśli zostanie rozwiązany lub odrzucony, muszę rozpocząć kolejne zadanie, aby kontynuować. Nie mogę wymyślić sposobu, aby to zrobić z Promise.all lub Promise.race, ponieważ nadal pracuję z obietnicami w tablicy i nie mogę znaleźć sposobu, aby je usunąć. Więc tworzę pracownika, który załatwia sprawę
Potrzebuję funkcji generatora obietnic, która zwraca obietnicę, która w razie potrzeby rozpatruje lub odrzuca. Jest wywoływana przez funkcję, która tworzy ramy, aby wiedzieć, co robi obietnica.
W poniższym kodzie generator po prostu zwraca obietnicę na podstawie setTimeout.
Tutaj jest
//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 zwraca obiekt zawierający przyrzeczenie i jego stan oraz zwróconą wartość.
Poniższy kod uruchamia pętlę, która testuje stan i tworzy nowe procesy robocze, aby zachować 3 uruchomione procesy robocze.
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();
Przetestowano w node.js.
Przy okazji, nie w tej odpowiedzi tak bardzo, ale w innych na podobne tematy NIENAWIDZĘ, gdy ktoś mówi „nie rozumiesz” lub „tak to nie działa”. Generalnie zakładam, że pytający wie, czego chce. Sugerowanie lepszego sposobu jest świetne. Cierpliwe wyjaśnienie, jak działają obietnice, również byłoby dobre.