Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to debug javascript promises?

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?

like image 935
YemSalat Avatar asked Sep 13 '14 20:09

YemSalat


People also ask

Can you debug JavaScript?

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.

Why is JavaScript so hard to debug?

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.


1 Answers

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.

So, what can be done?

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.

like image 137
Benjamin Gruenbaum Avatar answered Oct 19 '22 13:10

Benjamin Gruenbaum