Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cancel a promise chain?

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?

like image 992
panthro Avatar asked Jun 22 '15 19:06

panthro


People also ask

How do you abort a promise 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.

Is it possible to cancel a promise?

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 .

How do I cancel pending promise?

To force cancel a promise with JavaScript, we use the AbortController constructor. const controller = new AbortController(); const task = new Promise((resolve, reject) => { //... controller. signal.

Does promise race cancel promises?

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.


2 Answers

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)

like image 186
Adam Avatar answered Nov 05 '22 03:11

Adam


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
    });
like image 31
Safari Avatar answered Nov 05 '22 03:11

Safari