0

assume I have a service that returns items list and it called with a query word and then return a promise with the results. When it called twice(each time with a different query word), sometimes the old results are finally returned instead of the new one. What is the best way to solve it? There is any way to cancel promise? with pure js (and not observable)

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
GO VEGAN
  • 1,113
  • 3
  • 15
  • 44
  • 1
    A more concrete example would help here. – deceze May 21 '19 at 07:27
  • Please refer https://stackoverflow.com/questions/30233302/promise-is-it-possible-to-force-cancel-a-promise – Sharan Mohandas May 21 '19 at 07:32
  • 1
    Possible duplicate of [Cancel a vanilla ECMAScript 6 Promise chain](https://stackoverflow.com/questions/29478751/cancel-a-vanilla-ecmascript-6-promise-chain) – strah May 21 '19 at 07:34
  • Make sure you have `cache: false` in your ajax call. – Mohammad Arshad Alam May 21 '19 at 07:36
  • `var cancelled = false; promise.then(result => { if (!cancelled) { /* apply result */ } });` is all you need to prevent the callback from running (and overriding your newer result) by setting `cancelled = true`. – Bergi May 21 '19 at 08:23
  • If you want "cancel" to mean "immediately take the error path", then use `Promise.race()` to race your promise of interest against a promise initialised with a [cancellation token](https://stackoverflow.com/a/30235261/3478010); and chain from the promise returned by `Promise.race()`. – Roamer-1888 May 21 '19 at 16:57

1 Answers1

0

I always heard that you can't cancel Promises. That was actually one of the main points of difference to observables - you can cancel an observable. Yes, you could create an observable and then transform it to a Promise. But taking a fresh look at the Bluebird API (Bluebird is one well known library for handling Promises - that with adoption into ES2015 and latest JS development starts becoming obsolete) I see that they have a cancel method :

http://bluebirdjs.com/docs/features.html#cancellation-and-timeouts

From the example in Bluebird's docs :

// Enable cancellation
Promise.config({cancellation: true});

var fs = Promise.promisifyAll(require("fs"));

// In 2000ms or less, load & parse a file 'config.json'
var p = Promise.resolve('./config.json')
    .timeout(2000)
    .catch(console.error.bind(console, 'Failed to load config!'))
    .then(fs.readFileAsync)
    .then(JSON.parse);

// Listen for exception event to trigger promise cancellation
process.on('unhandledException', function(event) {
    // cancel config loading
    p.cancel();
});

You'd still had to add a library. Plain JS is possible if you write your promises with cancellation in mind, but you're always subject to other APIs. For example, you can abort a XHR request, but many other promises you can't cancel. Still from the Bluebird's docs, I POST here this example :

function makeCancellableRequest(url) {
    return new Promise(function(resolve, reject, onCancel) {
        var xhr = new XMLHttpRequest();
        xhr.on("load", resolve);
        xhr.on("error", reject);
        xhr.open("GET", url, true);
        xhr.send(null);
        // Note the onCancel argument only exists if cancellation has been enabled!
        onCancel(function() {
            xhr.abort();
        });
    });
}

You can design your promises in such way, maybe, depending on your use case.

Francisco
  • 2,018
  • 2
  • 16
  • 16