BanksySan BanksySan - 1 month ago 6
Javascript Question

throw new Error(string) not showing in F12

I have a JS script that thrown an

Error


$.when(verifyInitArgs(initArgs))
.then(function argsAreValid() {
initialiseForm();
}, function argsInvalid(error) {
throw new Error(error);
});


the
error
variable is a
string
. I can see this with
typeof
when a breakpoint is set:

>> typeof error
"string"


However, the thrown error is not showing in the console window in IE or Firefox.

If I enter
throw new Error("something");
directly in the browser console then it works as expected, it's displayed as an error in the console.

What's happening here?

Answer

Recall that then (and catch and such) create a new promise that the code in your callback can affect the outcome of. In the Promises/A+ style of promises (JavaScript's native promises adhere to those semantics, and jQuery's been trying to bring Deferreds in line — and the v3.1.1 you're using is in line now I believe), when you throw in a promise then or catch callback, that exception is converted into a rejection of the promise created by the then or catch method.

So your throw new Error(...) is becoming a rejection of the promise returned by your call to then.

Browsers are updating their handling of unhandled rejections so that those appear in the console (support for this varies at present); it may be worth switching over to native promises.

Just for illustration, here's an example of a native promise throwing within a then callback:

new Promise(function(resolve) {
  console.log("First promise resolving");
  resolve("all good");
}).then(function(resolution) {
  console.log("Got resolution " + resolution);
  console.log("Throwing error from second promise");
  throw new Error("ack!");
});

In recent Chrome, when you run that, if you open the real console (not just the in-snippet one) you'll see

Uncaught (in promise) Error: ack!(…)

...to report the unhandled rejection.

In contrast, using jQuery v3.1.1, I don't see that error:

var d = $.Deferred();
d.promise().then(function(resolution) {
  console.log("Got resolution " + resolution);
  console.log("Throwing error from second promise");
  throw new Error("ack!");
});
console.log("First promise resolving");
d.resolve("all good");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

...which is why it may be useful to switch over to native promises (if feasible in your project).