Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

es6 promises swallow type errors

I want the browser to show an error message when a type error occurs.
errors like can not read property something of undefined or undefined reference.

new Promise(function(resolve,reject){
    // do stuff ...
    reject('something logical is wrong');
}).catch(e => console.error(e));

new Promise(function(resolve,reject){
    // do stuff, and a syntax error :/
    var a = { };
    a.something.otherthing = 1; /* we have an error here */
    // ... 
}).catch(e => console.error(e));

In the first example the error is a logical one, and its fine to catch it in the catch(..) block.
But in the second example it is a clear development error, which happens all the time while developing new stuff. I don't want to catch it, i want the browser to show me the error like other errors in the console. I want to be able to turn on chrome pause on exceptions and see the state of other variables. I want to see the stack trace in console.
I want it to act like a normal error.

Any idea?

like image 972
Amin Roosta Avatar asked Oct 27 '15 18:10

Amin Roosta


People also ask

How do you prevent promises swallowing errors in JS?

Javascript. Now let us look into our problem statement with which we have to prevent promises swallowing errors. Consider the following code snippet (code example), in which a scenario is illustrated (which is based on real-time working) in which we implemented chaining of . then() method one after the another.

How do you handle errors from promises?

Errors inside the Promises If you throw an error inside the promise, the catch() method will catch it, not the try/catch. In this example, if any error in the promise1, promise2, or promise4, the catch() method will handle it.

Can you throw an error in a promise?

Any time you are inside of a promise callback, you can use throw . However, if you're in any other asynchronous callback, you must use reject . Instead you're left with an unresolved promise and an uncaught exception. That is a case where you would want to instead use reject .


2 Answers

Unlike exceptions in synchronous code, which become uncaught as soon as code returns to idle, a browser generally doesn't know the logical end of a promise-chain, which is where an asynchronous error could be considered uncaught. Chains are dynamically assembled after all, and therefore better be terminated with a final .catch at the logical end of the chain i.e. the asynchronous equivalent of idle.

Having a final .catch(e => console.error(e)) seems very reasonable to me, but you're right that browsers tend to display these errors differently from uncaught exceptions. If you want them to appear the same, you can use this trick:

.catch(e => setTimeout(() => { throw e; }))

This will throw e, containing the original stack trace and line number, on the very next cycle, and outside of the promise chain, where nothing will catch it and it will be reported as uncaught. We use setTimeout to overcome the default behavior of .catch which is to capture any exceptions in-chain in case you intend to keep on chaining.

With this, I hope you see that any differentiation between "logical" and other errors is irrelevant. Any error that makes it to the tail of the chain was fatal to the chain i.e. uncaught (though of course you can triage "logical" from other errors in the final catch and display them differently if you choose.)

like image 105
jib Avatar answered Oct 12 '22 16:10

jib


chrome has an option Pause on Caught Exceptions in Sources tab, i enabled that option and Pause on Exceptions feature is working fine now.

like image 26
Amin Roosta Avatar answered Oct 12 '22 14:10

Amin Roosta