Hacker News new | ask | show | jobs
by gfxmonk 4521 days ago
It's not just a best practice - exceptions raised from async code callback simply do not work right (they'll never make it back to the caller). In practice an exception raised from a callback will take a very short trip the wrong way through the stack (whatever happened to invoke your callback is _not_ the original caller, otherwise you wouldn't need callbacks), and end up as a toplevel uncaught exception, killing your entire process in nodejs.
2 comments

Good point. I had previously thought the callback in some way "remembered" who called it, and could bubble an exception back up to the caller's try/catch block. But you've set me straight. Further proving the point that you can't just throw exceptions whenever you want.
Actually, you can throw exceptions from within .then just fine and they will be always bubbled. You just cant go

  function g() {
    return somePromise.then(function() { 
      setTimeout(function() {
        throw new Error();
      }, 500);
    });
  }
  g(); // crash
But at that point, you're not using promises anymore so all bets are off.

However if you use a promise-based timeout too:

  function f() {
    return somePromise.then(function() {
      return Q.delay(1000).then(function() {
        throw new Error("Oops");
      });
    });
  }
  f().catch(function(e) {
    console.log(e.message); // logs Ooops.
  });
No problem bubbling that.
Don't promises address this exception problem because the top level code is calling the then () function, which can then throw an exception to the appropriate caller?
Yes, I believe so. I was just addressing a the original suggestion, which was to avoid using promises and use vanilla callbacks instead. In that architecture, exceptions don't seem to be workable.
Promises normalize all exceptions in promise code to bubble up the chain - as such, they do make it back to the caller.

(However, they do leave async exceptions from callbacks alone - only domains can handle those)