I am trying to understand how to debug asynchronous code that is based on promises. By Promises I mean ECMAScript 6 based promises and by debugging I mean using the built-in chrome or firefox debugger.
What I am having trouble with - is that when an error occurs I can't seem to get the stack trace no matter how I 'reject' it.
I tried these:
console.log(new Error('Error occured')); throw new Error('Throwing an Error'); return new Error('Error returned by the onRejected function'); reject(new Error('Pass Error to the reject function'));
But none of those returns the actual error in the code, or the stack trace.
So my question is - how to properly debug javascript Promises?
But fortunately, all modern browsers have a built-in JavaScript debugger. Built-in debuggers can be turned on and off, forcing errors to be reported to the user. With a debugger, you can also set breakpoints (places where code execution can be stopped), and examine variables while the code is executing.
What makes JavaScript great is also what makes it frustrating to debug. Its asynchronous nature makes it easy to manipulate the DOM in response to user events, but it also makes it difficult to locate problems.
This is a great topic to discuss, the sad news are this is actually quite hard with native promises.
Debugging raw ES6 promises in Chrome is horrible. This is because they will silently suppress errors and whenever you omit a catch it will not give you any indication that the promise failed. Update: Chrome now logs unhandled rejections (see this link for how)
Promise.resolve("foo").then(function(){ throw new Error("You will never see this");// silent failure });
In Firefox, things are a bit better since they perform unhandled rejection detection - however, it's still flakey and if you assigned the promise anywhere it won't work.
Include Bluebird - it's a superset of ES6 promises and you can swap it right inside, it has a richer API, it's faster and it has amazing stack traces. It's built with debugging in mind and includes great error handling facilities.
Once you've included Bluebird, call:
Promise.longStackTraces();
Which will slow it down a bit (it'll still be very fast) and will give you amazing error messages. For example:
Promise.resolve().then(function outer() { return Promise.resolve().then(function inner() { return Promise.resolve().then(function evenMoreInner() { a.b.c.d() }); }); });
In native promises - this will be a silent failure and will be very hard to debug - with Bluebird promises this will show a big red error in your console by default giving you:
ReferenceError: a is not defined at evenMoreInner (<anonymous>:6:13) From previous event: at inner (<anonymous>:5:24) From previous event: at outer (<anonymous>:4:20) From previous event: at <anonymous>:3:9 at Object.InjectedScript._evaluateOn (<anonymous>:581:39) at Object.InjectedScript._evaluateAndWrap (<anonymous>:540:52) at Object.InjectedScript.evaluate (<anonymous>:459:21)
Once you're done debugging - you can swap it out and go back to native promises. Personally I value knowing I have errors in production so I don't recommend it but it's certainly doable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With