Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uncaught exception doesn't raise #170

Closed
industral opened this issue Jul 17, 2013 · 4 comments
Closed

Uncaught exception doesn't raise #170

industral opened this issue Jul 17, 2013 · 4 comments

Comments

@industral
Copy link

I found, that if in code I have uncaught exception, and that particular part of code is promise object, exceptions couldn't be catches by "uncaughtException" event.

process.on("uncaughtException", function(err) {
  console.error("Caught exception: " + err);
});

var $when = require("when");

function main() {
  check().then(function() {
    console.log("check OK");

    getInfo().then(function() {
      console.log("getInfo OK");
    }, function() {
      console.log("getInfo FAILED");
    });
  }, function() {
    console.log("check FAILED");
  });
}

function check() {
  var deferred = $when.defer();

  deferred.resolve(true);

  return deferred.promise;
}

function getInfo() {
  var deferred = $when.defer();

  asd.asd;  // uncaught exception

  deferred.resolve();

  return deferred.promise;
}

main();

Here we have asd.asd that doesn't exist, but exception haven't catch.

In console we have:
check OK

@skiadas
Copy link
Contributor

skiadas commented Jul 17, 2013

I think this works properly. Your function getInfo when executed raises an exception, and never returns its promise. Now it is being executed inside the outer "then", and there's nothing to catch it. If you had used something like a .otherwise() and put the "else" clause of your outer "then" there, following that outer then, then it would have caught it.

Basically: Code inside a "then" is sort of in a "promise" state. It can never raise an exception. It is sort of as if you ran it in a try catch block, where you resolve if the try goes through and reject if you fall in the catch part.

If you do want to handle that exception, you'll have to do something like:

 }, function() {
    console.log("check FAILED");
  })
  .otherwise(handleErrorFunction);
}

@briancavalier
Copy link
Member

@industral yes, @skiadas is on the mark here. I'll try to add a bit of background.

Promises provide a powerful asynchronous analog to synchronous exceptions. The promise machinery must catch exceptions and transform them into promise rejections (see 3.2.6.2 in the Promises/A+ spec.

Because promises have a temporal component which synchronous exceptions don't, a rejected promise that is "unhandled" in one instant may become handled in some future instant when some code adds a rejection handler to it. Thus, at any instant you might deem a rejection "unhandled", in the very next instant, it might be handled.

Rejections still travel back through a promise chain similarly to how exceptions propagate, so adding a rejection handler at a higher level, via .otherwise as you would with a catch statement is the typical best practice.

One problem is that Javascript VMs aren't yet promise-aware, so rejections that remain unhandled forever will be silent. when.js (>= 2.2.0) includes a promise monitoring system that can detect and report unhandled rejections--it will also detect if/when they later become handled. It will even attempt to stitch together call stacks across event loop turns to recreate a "long stack trace" of the rejection's lifetime (where the promise was created, where it was rejected, etc.)

The default monitor reports information to the console, but you could potentially create your own (based on this and this) that rethrows exceptions in a future event-loop tick (and thus are uncatchable), and then install an uncaughtException handler in node to catch them.

That's pretty roundabout, though, and I think you'll find that once you get used to handling errors with promises, it's quite intuitive and powerful.

Hope that helps!

EDIT: Add missing links to monitor console and rethrowToHost code

@industral
Copy link
Author

@briancavalier Thanks a lot!

@briancavalier
Copy link
Member

Cool, glad that helped. I forgot to add some links above, so I just edited my comment and added them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants