At first glance, it looks like the output will be
error statting. Running the program shows something else:
throw is in a callback which gets executed long after the rest of the code has finished running. If anything is going to catch this error, it’s in
For the most part, your programs are going crash if any callback in a chain throws an error. To prevent this, you have to get used to wrapping tons of stuff in try/catch or engaging in ludicrously defensive programming.
Before some self-proclaimed Node expert tells me to stop throwing errors in callbacks, I’ll point out that the Node.js API docs contain plenty of examples. Basic stuff like reading files uses this pattern. More importantly, it’s easy to unintentionally throw an error. Accessing a property of an undefined variable is a common mistake, and will throw a ReferenceError.
I know people have said this before, but it’s insane that Node runs its own web server. By default, a single unhandled error will cause your web server to crash. Here’s an example:
This web server capitalizes whatever you send to it. Like so:
Neat, eh? Well let’s try throwing some more complicated data at it:
What’s this?! Going back to the other terminal, I see that Node.js has crashed:
That sucks, now what can we do about it?
To stop the web server from crashing, the typical solution is to add an uncaught exception handler:
But that doesn’t completely solve the problem. The user gets no useful error message, just a timeout. Also, you the programmer still have to write a bullet-proof error handler. If your code throws an error trying to log a stack trace, it’s lights-out for your web server. Putting your handler code in a big try/catch can mitigate this, but that’s effectively writing an error handler for your error handler. The fact that such a solution is required by Node.js is a bad code smell.
Hopefully, errors will be more isolated in the future. Node.js 0.8 will introduce domains, which make it easier to handle errors with more granularity. Domains seem like a good idea, but they introduce a third way of handling errors.
For now, Node.js forces you to reinvent the wheel. Web servers solved these problems over a decade ago, but Node’s coupling between web server and application prevents you from using those solutions.