Typescript: subclass/extend of Promise gives 'TypeError: undefined is not a promise' on run time
Asked Answered
F

1

1

I'm trying to cancel my async method call in Typescript.

To do this, I have created a new Promise type, which inherits from Promise:

class CancelablePromise<T> extends Promise<T>{

    public cancelMethod: () => void;
    constructor(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void) {
        super(executor);
        // Set the prototype explicitly.

        Object.setPrototypeOf(this, CancelablePromise.prototype);

    }

    //cancel the operation
    public cancel() {
        if (this.cancelMethod) {
            this.cancelMethod();
        }
    }
}

The first version was without the Object.setPrototypeOf(..), but it was recommend on the TypeScript GitHub page

When I'm trying to use it, I get a run-time error (no compile errors):

class Test{

    async postFileAjax<T>(file: File): CancelablePromise <T> { 

        var promiseFunc = (resolve) => { resolve() };
        var promise = new CancelablePromise<T>(promiseFunc);
        promise.cancelMethod = () => { console.log("cancel!") };

        return promise;
    }
}

var test = new Test();
test.postFileAjax(null);

Error:

(unknown) Uncaught TypeError: undefined is not a promise
    at CancelablePromise.Promise (<anonymous>)
    at new CancelablePromise (<anonymous>:44:28)
    at __awaiter (<anonymous>:7:12)
    at Test.postFileAjax (<anonymous>:62:16)
    at <anonymous>:75:6
    at HTMLButtonElement.excuteButton.onclick (https://www.typescriptlang.org/play/playground.js:242)

What am I doing wrong? I see that in ES6 you could subclass the Promise (see stackoverflow question), so I would expect it also in TypeScript.

Using Typescript 2.1 and targeting es5

You can see the same result if you run the code in TypeScript Playground, click "run" and check the console (F12) in the new page.

Error in console

How do I solve this runtime error?


PS: a related error on stackoverflow is here, but that a compile error and solved. I have split the compile and runtime error.

Fetation answered 14/4, 2017 at 22:46 Comment(3)
What is the reason for Object.setPrototypeOf(this, CancelablePromise.prototype);?Harrietteharrigan
@Harrietteharrigan it's from the link (also included in the post) "Recommendation - As a recommendation, you can manually adjust the prototype immediately after any super(...) calls."Fetation
You cannot cancel promises. I think you are thinking of Maybes...Cushy
G
3

I simplified your example; this runs without error:

interface CancelablePromise<T> extends Promise<T> {
    cancel: () => void;
}

class Test {
    postFileAjax<T>(file: File): CancelablePromise<T> {
        const promiseFunc = (resolve) => { resolve() };
        const promise = new Promise<T>(promiseFunc);
        const cancel = () => { console.log("cancel!") };
        const cancelablePromise = Object.assign(promise, { cancel });
        return cancelablePromise;
    }
}

const test = new Test();
const testPromise = test.postFileAjax(null);
testPromise.cancel();

TypeScript Playground

  • I used interface inheritance rather than a new class.
  • I copied the cancel function right onto promise.
Gynecoid answered 16/4, 2017 at 6:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.