The next topic is handling asynchronous errors. So you know that node.js, it's all about asynchronous non-blocking code. But, there is a tricky part with asynchronous when we get the event loop involved, we lose that context. So when we lose the context, "Try/catch" is not good enough. Because "Try/catch", will not help us with asynchronous errors.
Consider this example. So we throwing an error, it could be some real error, but in this case we manually creating an error by throwing it and our "Try/catch" is...it's kind of okay. Actually, it's working. Wow, this is good. Okay. So maybe I was wrong. So let's take a look at the newsline. This is asynchronous error. So, the error is not happening at the same time. "setTimeout" will execute, quote unquote execute the error. It will make sure the error happened in the future. So at some point in the future, by using the call back. So this is asynchronous code and the app actually crashes. It fails miserably. So what is happening? Why this is happening?
Well, that is because of the event loop and that's nature of node.js. So "Try/catch" is pretty much useless because most of the times, we are using non-blocking asynchronous code. When you're just using synchronous code, like JSON.parse, that's fine. Use "Try/catch".
That's the great idea. But in other cases, let's say using express.js, middleware, you getting some data from the database. Well, if error happens in the call back of the database call, your "Try/catch" in the beginning will not catch that. It will be absolutely useless. So don't use "Try/catches" for handling asynchronous errors or you would fail like this elephant. Don't. Don't do that. But what can we use? How can we deal with it? So there are some best practices.
So, first of all, listen to all "on error" events. So, by "on error" events, again, I'm referring to that event emitter pattern to events. So, most of the objects, most of the classes like server, HTTP request, HTTP response, so most of them, they have an error event emitted from those modules. So if you create an event listener, you would be able to catch that, and then exit accordingly.
Shut down, save everything. So that will allow you to basically handle errors better. Never, never emit using those "on error" event listeners, because if you emit there it would be just silent. And then your app might crash, or it might not crash depending on the situation. Then the last step, the last resort, so to say, is to listen for uncaught exceptions. So, uncaught exceptions is the very last thing that happens before the node.js script, the node.js app will crash. So before it crashes, you can catch the kind of the last step, the last breath, you can catch that thing. And what should you do?
You should definitely log that error, log that pesky error and so later you can debug it, do postmortem, trace it, notify, like send an emails, like a HitChat, Slack notification... URL, post requests to a URL. And when you inside a uncaught exception, the key here is not try to resume whatever problem was. The key here is just to exit and restart. Exit with a bad code. Exit with a code one, for example. So whoever started your process knows that this was an error. It wasn't a normal operation. And then use a domain maybe. We will talk about domain or AsyncWrap maybe, some of those things. But let's consider some of the examples of server.on error, for example.
So server dot's available in all of those frameworks because all of those frameworks like Express, LoopBack, Sails, Hapi , they extend from server. Server meaning the core HTTP. And you obviously need to have that "on-error" in all of them. You can change the method. There is nothing wrong with changing the method.
You don't have to use a new line. So what you need to do inside, you need to trace it, you need to log it, and then you need to exit it with code one. Obviously, if you don't change it, you can use a named variable. So "http.request", that's another example of a core object and we can use the same. We can listen to the same event on-error here as well.