I chain a series of promises:
this.getData.then(this.getMoreData).then(this.getEvenMoreData);
At some point the user may decide to cancel the request and request something else.
How can I cancel the propagation of the chain?
Sometimes in a promise chain, you need to abort the chain and prevent any additional then / catch / finally from running. In simple cases, this can be done by just throwing an exception and catching it at the end of the chain.
Promises have settled (hah) and it appears like it will never be possible to cancel a (pending) promise. Instead, there is a cross-platform (Node, Browsers etc) cancellation primitive as part of WHATWG (a standards body that also builds HTML) called AbortController .
To force cancel a promise with JavaScript, we use the AbortController constructor. const controller = new AbortController(); const task = new Promise((resolve, reject) => { //... controller. signal.
race() The Promise. race() method returns a promise that fulfills or rejects as soon as one of the promises in an iterable fulfills or rejects, with the value or reason from that promise.
You'd have to check for the state (of whether you should cancel or not) inside each chained method:
var userRequestedCancel = false;
this
.getData()
.then(function() {
if(userRequestedCancel) {
return Promise.reject('user cancelled');
}
return getMoreData();
})
.then(function() {
if(userRequestedCancel) {
return Promise.reject('user cancelled');
}
return getEvenMoreData();
})
Or perhaps a slightly more elegant way (edited to pass context and arguments to callback
methods)
var currentReq = false;
var userRequestedCancel = false;
var shouldContinue = function(cb,args) {
if(userRequestedCancel) {
return Promise.reject('user cancelled');
}
currentReq = cb.apply(this,args);
return currentReq;
}
var onCancel = function() {
userRequestedCancel = true;
currentReq && currentReq.abort();
}
this
.getData()
.then(function() {
return shouldContinue(getMoreData,arguments);
})
.then(function() {
return shouldContinue(getEvenMoreData,arguments);
})
If you need to cancel the current request as well, that is kind of trivial, set your current ajax
request to be a global variable, and whatever event sets the userRequestedCancel
flag to true, have that also cancel the ajax
request (see edited code above)
In order to cancel a promise chain you need to throw an error. Just have a look at the code below
function CancelError() {
this.message = 'Cancelled';
}
obj
.then(function() {
throw new CancelError();
})
.catch(function(err) {
if (err instanceof CancelError) {
// Promise got cancelled
}
throw err; // throw the other mistakes
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With