1

Is it normal that I get an unhandled exception error from a reject(new SomeKindOfError()) within a promise while debugging in VS Code, but not when I'm not debugging? Or is there something wrong from my code structure?

From what I have learned from several tutorials about promises and stackoverflow answers, a Promise#catch() at then end of a promise chain is enough to catch a rejection that might occur in the chain. But why is it still marked as an unhandled exception by the debugger?

Here's the structure I used:

function returnAPromise(): Promise<any> {
    return new Promise<any>((resolve, reject) => {
        // do something here
        if (isConditionMet) {
            resolve()
        } else {
            reject(new SomeKindOfError()) // debugger breaks here
        }
    })
}

someElement.onSomeEvent(() => {
    // only care about the errors that might occur
    returnAPromise().catch((error) => {
        if (error instanceof SomeKindOfError) {
            // perform necessary actions when this error occurred
        }
    })
})

P.S. I already tried out debugging without performing break when an unhandled exception is encountered but it kind of defeats the purpose of using the debugger: to check out for unhandled exception that might occur.

Edit:

Unhandled exception error from a reject

Also, I tried calling returnAPromise() without a catch and that one prints a warning in the debugger console saying rejected promise not handled within 1 second.

bmdelacruz
  • 2,366
  • 1
  • 19
  • 26
  • Nvm about my answer below. I see what you mean now. I thought you were asking why it is always in catch block. – serdar.sanri Apr 06 '17 at 20:05
  • Are you really getting an "unhandled rejection" there? Afaik you can make your debugger to implicitly break on every `Error` being created, regardless whether it will be caught later or not. – Bergi Apr 06 '17 at 20:41
  • Hi @Bergi, I added a screenshot in my post. It seems that I'm not really getting an unhandled rejection there since I'm not getting a warning (like the one that I described on my edit), but still, the debugger is breaking there. – bmdelacruz Apr 07 '17 at 07:33
  • 1
    Yes, looks quite like it is breaking on the Error constructor. – Bergi Apr 07 '17 at 12:01
  • is there anything you can suggest to suppress that behaviour? – bmdelacruz Apr 07 '17 at 13:57
  • thanks again, @Bergi for pointing that out. – bmdelacruz Apr 07 '17 at 14:20

1 Answers1

0

Thanks @Bergi for pointing out that it's because of the Error constructor. I did not notice that... :'(

It turns out, the problem is not because of the promise not catching it. It's because of an error in extending built in Typescript classes.

Here's a stackoverflow post I found, which refers to this Typescript documentation about breaking changes in v2.1.

Extending built-ins like Error, Array, and Map may no longer work. As part of substituting the value of this with the value returned by a super(...) call, subclassing Error, Array, and others may no longer work as expected. This is due to the fact that constructor functions for Error, Array, and the like use ECMAScript 6's new.target to adjust the prototype chain; however, there is no way to ensure a value for new.target when invoking a constructor in ECMAScript 5. Other downlevel compilers generally have the same limitation by default.

Because of this, I have to add an additional line of code in the constructor of the class that extends the Error class.

class SomeKindOfError extends Error {
    constructor(m: string) {
        super(m)

        // I have to add this additional line of code
        Object.setPrototypeOf(this, SomeKindOfError.prototype)
    }
}
Community
  • 1
  • 1
bmdelacruz
  • 2,366
  • 1
  • 19
  • 26