2

I am using native Promises for making ajax requests with superagent like this.

function callAPI() {
    return new Promise(function () {
        request.get('/some.json')
            .end(function (error, res) {
                resolve(res);
            });
    });
}

var reqProm = callAPI();

What I am wondering is, can I use this promise to cancel/abort the request made? I would think there should be a method in Promise.prototype like the following.

function callAPI() {
    new Promise(function (resolve, reject) {
        this.req = request.get('/some.json')
            .end(function (error, res) {
                resolve(res);
            });
    });
}

Promise.prototype.abort = function () {
 this.req.abort();
} 

However, I'm getting an error saying Promise.prototype is readonly. Is there any better way to do this?

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Salman
  • 9,299
  • 6
  • 40
  • 73
  • 1
    In what world (that is, in which browser) is Promise.prototype read-only?? I just tested in Safari, Chrome and Fx and the prototype is definitely writable. – Touffy Sep 25 '15 at 09:37
  • (to be more precise, you can't redefine Promise.prototype but you can add new properties to it) – Touffy Sep 25 '15 at 09:45
  • I'm getting error while linting and transpiling. May be its set on strict check mode which I can't change. – Salman Sep 25 '15 at 10:06
  • Strict mode should not prevent extending a native constructor's prototype. One of your preprocessing tools is just making up rules here. What are you using? – Touffy Sep 25 '15 at 12:59

3 Answers3

3

I'm getting an error saying Promise.prototype is readonly

I think this isn't true. What is the error you are receiving?

What I am wondering is, can I use this promise to cancel/abort the request made?

Instead of returning the new Promise you create, store it in a closure and return the Promise instance with an extra method that has scope to call the abort method on req and also the reject method of the Promise.

As a side note, in your first example you are attempting to call resolve within your new Promise but are not making it available by accepting the resolve and reject functions as arguments to the Promise constructor executor.

function callAPI() {
    let _reject;
    let _req;

    let promise = new Promise(function (resolve, reject) {
        _reject = reject;
        _req = request.get('/some.json').end(function (error, res) {
            resolve(res);
        });
    });

    promise.abort = function () {
        _req.abort();
        _reject();
    };

    return promise;
}

let call = callAPI();

call.abort();
sdgluck
  • 24,894
  • 8
  • 75
  • 90
  • I started like this as well, but I gradually needed more and more `.then` and such. Obviously every chained promise needed to proxy `.abort` to the original promise too. Since it became very messy, I was hoping for a more generic solution. – rr- Jan 07 '17 at 16:10
1

You've got a semantic issue here. A Promise is not the same thing as the thing that returns a Promise. In your case, the request is the thing you want to potentially abort.

If anything, the Promise represents the response, not the request. It makes no sense to cancel a response, does it?

What would make sense is if you have an object representing the request, with an abort() method, and calling that method would reject the related Promise.

Touffy
  • 6,309
  • 22
  • 28
0

You are doing a wrong thing.

return new Promise(function (resolve, reject) {
  this.req = request.get('/some.json')

Now promises returned from your function have the req property.

Promise.prototype.abort = function () {
  this.req.abort();

And promises created anywhere have abort function which uses req field.

You have to create your own class inhereted from promice and modify its prototype, but not the Promise prototype.

Qwertiy
  • 19,681
  • 15
  • 61
  • 128
  • Hey! Its strange that `new Promise(function () { console.log(this === window); //true });`. So attaching `this.req` itself isn't possible. Any idea? – Salman Sep 28 '15 at 04:31