I have tried using Promise.race(), but in this case too if one of the Promise is resolved the other Promises keep on running.
Is there a way to stop other processes from running once one of them wins.
I do not want other processes to keep running and using system resources.
I am open to use other ways instead of promises to implement this.
In practice PromiseA is waiting for PromiseZ (I am using the following code to mock similar behaviour)
Since I know now after running PromiseA that PromiseB is not required, I want to stop PromiseB
Is there any better way to do this?
var promiseList = [];
var flag = false;
function PromiseA() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log(flag)
flag = true;
resolve();
}, 2000);
});
}
function PromiseB() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
if (flag === true) {
console.log('checking')
console.log('flag is:' flag)
resolve();
} else {
reject();
}
}, 7000);
});
}
promiseList.push(PromiseA());
promiseList.push(PromiseB());
Promise.all(promiseList);
CodePudding user response:
According to ECMAScript specification you can not cancel an ongoing promise.
However you can abort a fetch request using AbortController
which be used not only for fetch but also for other asynchronous tasks.
- https://developer.mozilla.org/en-US/docs/Web/API/AbortController/abort
- https://javascript.info/fetch-abort
Is there a way to stop other processes from running once one of them wins.
You can chain the expensive computation in a way to run once the earlier promise is resolved.
If you want to cut down on server resources you can run each promise one by one or chain them.
const promiseA = () => new Promise((resolve, reject) => reject('Some value'));
const promiseB = () => new Promise((resolve, reject) => resolve('Other value'));
Promise.resolve(10)
.then(promiseA).catch(promiseB)
.then(val => console.log(val))
.catch(err => console.log(err));
CodePudding user response:
Following up on my comment:
The Promise
API does not support cancellation. Therefore, you'll have to design a cancellation mechanism into your own API.
Here's a slight modification to the code in your question which does exactly that using the AbortController
API:
let flag = false;
function PromiseA(abortSignal) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
if (abortSignal.aborted) {
reject();
return;
}
console.log(flag)
flag = true;
resolve();
}, 2000);
});
}
function PromiseB(abortSignal) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
if (abortSignal.aborted) {
reject();
return;
}
if (flag === true) {
console.log('checking')
console.log('flag is:' flag)
resolve();
} else {
reject();
}
}, 7000);
});
}
async function main () {
const ac = new AbortController();
const promiseList = [
PromiseA(ac.signal),
PromiseB(ac.signal),
].map(p => p.then(() => ac.abort()));
await Promise.any(promiseList);
console.log('done');
}
main();