How to cancel last Promise if not resolved?

cancel promise
angular cancel promise
bluebird cancel promise
promise reject
async/await cancel promise
react cancel promise
clear promise
promise((resolve, reject))

Let's say I have a search function to make an HTTP call. Every call can take a different amount of time. So I need to cancel the last HTTP request and wait only for the last call

async function search(timeout){

   const data = await promise(timeout)
   return data;

}
// the promise function is only for visualizing an http call
function promise(timeout){
   return new Promise(resolve,reject){
       setTimeout(function(){      
           resolve()
       },timeout) 
   }
}
search(200)
.then(function(){console.log('search1 resolved')})
.catch(function() {console.log('search1 rejected')})
search(2000)
.then(function(){console.log('search2 resolved')})
.catch(function(){console.log('search2 rejected')})
search(1000)
.then(function(){console.log('search3 resolved')})
.catch(function(){console.log('search3 rejected')})

Need to see "search1 resolved" "search2 rejected" "search3 resolved"

How can I achieve this scenario?

Promises aren't cancelable as such, but are cancelled in a limited sense by causing them to be rejected.

With that in mind, cancellation can be achieved with a small amount of elaboration around Promise.race() and the promise-returning function you wish to be cancelable.

function makeCancellable(fn) {
    var reject_; // cache for the latest `reject` executable
    return function(...params) {
        if(reject_) reject_(new Error('_cancelled_')); // If previous reject_ exists, cancel it.
                                                       // Note, this has an effect only if the previous race is still pending.
        let canceller = new Promise((resolve, reject) => { // create canceller promise
            reject_ = reject; // cache the canceller's `reject` executable
        });
        return Promise.race([canceller, fn.apply(null, params)]); // now race the promise of interest against the canceller
    }
}

Assuming your http call function is named httpRequest (promise is confusing):

const search = makeCancellable(httpRequest);

Now, each time search() is called, the cached reject executable is called to "cancel" the preceding search (if it exists and its race has not already fulfilled).

// Search 1: straightforward - nothing to cancel - httpRequest(200) is called
search(200)
.then(function() { console.log('search1 resolved') })
.catch(function(err) { console.log('search3 rejected', err) });

// Search 2: search 1 is cancelled and its catch callback fires - httpRequest(2000) is called
search(2000)
.then(function() { console.log('search2 resolved') })
.catch(function(err) { console.log('search3 rejected', err) });

// Search 3: search 2 is cancelled and its catch callback fires - httpRequest(1000) is called
search(1000)
.then(function() { console.log('search3 resolved') })
.catch(function(err) { console.log('search3 rejected', err) });

If necessary, the catch callbacks can test err.message === '_cancelled_' in order to distinguish between cancellation and other causes of rejection.

How to Cancel Your Promise, callback is not needed anymore – we just attach `.then` // handler to result function updateUser() { let resolve, reject, cancelled; const promise  Promises aren't cancelable as such, but are cancelled in a limited sense by causing them to be rejected. With that in mind, cancellation can be achieved with a small amount of elaboration around Promise.race() and the promise-returning function you wish to be cancelable.

You can define a factory function to encapsulate your search() method with the requested cancellation behavior. Note that while Promise constructors are normally considered an anti-pattern, it is necessary in this case to keep a reference to each reject() function in the pending set in order to implement the early cancellation.

function cancellable(fn) {
  const pending = new Set();

  return function() {
    return new Promise(async (resolve, reject) => {
      let settle;
      let result;

      try {
        pending.add(reject);
        settle = resolve;
        result = await Promise.resolve(fn.apply(this, arguments));
      } catch (error) {
        settle = reject;
        result = error;
      }

      // if this promise has not been cancelled
      if (pending.has(reject)) {
        // cancel the pending promises from calls made before this
        for (const cancel of pending) {
          pending.delete(cancel);

          if (cancel !== reject) {
            cancel();
          } else {
            break;
          }
        }

        settle(result);
      }
    });
  };
}

// internal API function
function searchImpl(timeout) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, timeout);
  });
}

// pass your internal API function to cancellable()
// and use the return value as the external API function
const search = cancellable(searchImpl);

search(200).then(() => {
  console.log('search1 resolved');
}, () => {
  console.log('search1 rejected');
});

search(2000).then(() => {
  console.log('search2 resolved');
}, () => {
  console.log('search2 rejected');
});

search(1000).then(() => {
  console.log('search3 resolved');
}, () => {
  console.log('search3 rejected');
});

search(500).then(function() {
  console.log('search4 resolved');
}, () => {
  console.log('search4 rejected');
});

Promise Cancellation Is Dead, Okay, “You can't cancel a promise, unless it's from Bluebird”. const promise = new Promise((resolve, reject, onCancel) => { const id  One of the drawbacks of using promise chains is that we don’t have access to the lexical scope (or to variables in closure) of callbacks. You can read a great article how to solve this problem from Dr. Alex Rauschmayer. But, as soon it was discovered, you can not cancel a promise, and this is a

Similar to the answer of PatrickRoberts, I would suggest to use a Map to maintain a list of pending promises.

I would however not maintain a reference to the reject callback outside of the promise constructor. I would suggest to abandon the idea of rejecting an outdated promise. Instead, just ignore it. Wrap it in a promise that never resolves or rejects, but just remains a dead promise object that does not ever change state. In fact, that silent promise could be the same one for every case where you need it.

Here is how that could look:

const delay = (timeout, data) => new Promise(resolve => setTimeout(() => resolve(data), timeout));
const godot = new Promise(() => null);

const search = (function () { // closure...
    const requests = new Map; // ... so to have shared variables
    let id = 1;
    
    return async function search() {
        let duration = Math.floor(Math.random() * 2000);
        let request = delay(duration, "data" + id); // This would be an HTTP request
        requests.set(request, id++);
        let data = await request;
        if (!requests.has(request)) return godot; // Never resolve...
        for (let [pendingRequest, pendingId] of requests) {
            if (pendingRequest === request) break;
            requests.delete(pendingRequest);
            // Just for demo we output something. 
            // Not needed in a real scenario:
            console.log("ignoring search " + pendingId);
        }
        requests.delete(request);
        return data;
    }    
})();

const reportSuccess = data => console.log("search resolved with " + data);
const reportError = err => console.log('search rejected with ' + err);

// Generate a search at regular intervals.
// In a real scenario this could happen in response to key events.
// Each promise resolves with a random duration.
setInterval(() => search().then(reportSuccess).catch(reportError), 100);

Canceling Promises in JavaScript, If you can't stop a train, your train-stopping button will not — cannot — work. is called after the promise has completed, rejected or resolved. The Promise that is resolved with the given value or the promise passed as the value if the value was a promise object. The static Promise.resolve() function returns the Promise that is resolved. Let us take a simple example. Write the following code inside the app.js file.

Cancel Promise pattern (no cancellable promises), I'm not sure what you mean by "resumption". And what would that value be used for? Just basic Promise.race. If users were to resolve the cancel promise instead​  Fulfilled is a state of a Promise. It means that the promise has been resolved and now has its resolved value (using the internal resolve function). The operation represented by the promise has been completed successfully. Rejected. Rejected means that the promise has been rejected and now has its rejected reason (using the internal reject

Cancellation, The cancellation feature is by default turned off, you can enable it using Cancelling a promise simply means that its handler callbacks will not be called. reject, onCancel) { var xhr = new XMLHttpRequest(); xhr.on("load", resolve);  The Promise.resolve() method returns a Promise object that is resolved with a given value. If the value is a promise, that promise is returned; if the value is a thenable (i.e. has a "then" method), the returned promise will "follow" that thenable, adopting its eventual state; otherwise the returned promise will be fulfilled with the value. This function flattens nested layers of promise-like

await, If the value of the expression following the await operator is not a Promise , it's converted to a resolved Promise. An await can split execution  The “start” button starts a promise which resolves after 2.5 seconds. When hitting “stop/abort” during that timeframe however, the promise will be cancelled. AbortController Example

Comments
  • If you have multiple promises chained together- the chain will stop when one of them is rejected. You don't have them chained so they will all execute every time.
  • Aksi bit rekated ti question but you should move to async await its much simplier
  • this is not the scenario I want. I need to cancel only the last call of promise function if not yet resolved the promise function just visualize an async call like an API i want only the last promise to be resolve or any other promise that resolved before 1000 ms
  • Your Promise construction should be new Promise((resolve, reject) => ...), also, what's the problem logging promise2 resolved?
  • Your question is ambiguous. If really the last promise should be cancelled when a new request comes in, your code example should produce "search1 rejected", not "search1 resolved", since the second call of search should identify the previous promise as not resolved. If however, you want to give precedence to which-ever promise resolves first, then the output should be "search1 resolved", and the other two rejected. Please clarify the logic in your question, and make the code consistent with that explanation.
  • Your code does not produce the requested behavior. With your function, search(2000) causes search(200) to be cancelled immediately when search(2000) is called. The requested behavior was to cancel only if the second promise settles before the first. Note the request was for search(200) to resolve, not reject, because it settles before search(2000) does.
  • I don't know how you reached that understanding. It makes no sense.
  • Okay, well let's just look at what was explicitly stated then. They requested to see search1 resolved search2 rejected search3 resolved. Your solution does not do that.
  • I agree, but it does answer the headline question "How to cancel last Promise if not resolve[d]?"
  • Indeed, it is ambiguous.
  • I figured out what was bugging me about the premise of this. While I agree there are scenarios where you would prefer not to call .then() or .catch(), there are cases where this would leak resources released during finalization via .finally() or try { await ... } finally { ... }. For that reason, I think promises should always settle, even if you have to differentiate between a rejection due to an exception or cancellation.
  • @PatrickRoberts, of course, this is like saying "if my code expects A to happen, I should make A happen". If your code needs promises to settle to do some clean-up, you should... settle them. But promises are just objects, so you can just deal with them like that. How you deal with releasing resources is essentially not a promise-related topic. But again, if you design your code in a way that assumes that promises are always settled, then you should be consistent with that choice. I am not debating that, of course. See also this answer.
  • Thanks for the insightful response. I took a look at the answer you linked, but I'm still a bit baffled by the notion that "how you deal with releasing resources is essentially not a promise-related topic". I might be inclined to agree with that were it not for the fact that promises are deeply integrated into the language with the sole intention of signaling completion for non-blocking operations. If you remove the signaling of completion from the equation, you remove the ability to clean up manually allocated resources unless you use a WeakRef.
  • By the way, I don't dislike your answer (in fact your upvote is from me). I just wanted to make sure I clearly understood the design choice to remain unsettled rather than reject for cancellation.