‫In this video, let's talk about something
‫that we have in node.js called unhandled rejections
‫and then learn how we can actually handle them.
‫So at this point, we have successfully handled errors
‫in our express application
‫by passing operational asynchronous errors down
‫into a global error handling middleware.
‫This, then sends relevant error messages back to the client
‫depending on the type of error that occurred, right?
‫However, there might also occur errors outside of express
‫and a good example for that in our current application
‫is the mongodb database connection.
‫So imagine that the database is down for some reason
‫or for some reason, we cannot log in.
‫And in that case, there are errors
‫that we have to handle as well.
‫But they didn't occur inside of our express application
‫and so, of course, our error handler that we implemented
‫will not catch this errors, right?
‫And so just to test what happens, let's go ahead
‫and change our mongodb password, okay?
‫Because that way, we're not gonna be able
‫to connect to the database, right?
‫And so we should then get some kind of error,
‫and so let's go here to our server file
‫and save it in order to reload our server,
‫let's increase it here, and indeed,
‫here we have an unhandled promise rejection.
‫And so that is actually the topic of this video.
‫So an unhandled promise rejection means that somewhere
‫in our code, there is a promise that got rejected.
‫But that rejection has not been handled anywhere, all right?
‫And down here, you also see a deprecation warning
‫which says that in the future unhandled rejections
‫will simply exit the node program that's running,
‫which may not always be what you want, okay?
‫So let's fix this problem and get rid
‫of this unhandled promise rejection.
‫Now, in this simple example here,
‫it would be actually quite easy
‫to handle that rejection, right?
‫All we'll have to do would to come here
‫to this piece of code where our connection is actually done
‫and then, add a catch handler there, right?
‫So a bit like this, and then in here,
‫we could handle that rejection
‫and would then no longer get this error.
‫Let me just quickly show that to you.
‫So try it again.
‫And so now, you get error which is of course,
‫the result of this log here,
‫but of course, we get no unhandled promise rejection,
‫again, because we actually handled it here, all right?
‫So this would work, of course, but I really want to show you
‫how to globally handle unhandled rejected promises,
‫because in a bigger application, it can become a bit
‫more difficult to always keep track of all the promises
‫that might become rejected at some point, okay?
‫And so at some point, you might have some unhandled
‫promise rejection somewhere and so let me show you
‫how to deal with that globally basically.
‫And so let's now learn how to handle unhandled rejections
‫and we're gonna do that right here.
‫And so remember how in one of the first section
‫of the course, we talked about events
‫and event listeners, right?
‫And so now, it's time to actually use that knowledge.
‫So each time that there is an unhandled rejection
‫somewhere in our application, the process object
‫will emit an object called unhandled rejection
‫and so we can subscribe to that event just like this.
‫So process.on, remember, and then the name of the event,
‫unhandled rejection,
‫and then the callback function here
‫receives an error, and so let's actually go ahead
‫and log the error to the console.
‫So let's use err.name and err.message.
‫So these are kind of some defaults
‫that we have on all errors in node.js, all right?
‫Okay, and after saving, we already, down here
‫get the name of the error and also the error message.
‫So bad authentication which is because, of course,
‫we have the wrong password.
‫And so right now, the unhandled promise rejection
‫is now actually handled.
‫And of course, not just the one from this failed connection
‫but any other promise rejection that we might not catch
‫somewhere in the application is handled here in this final,
‫let's call it safety net, all right?
‫So we always have to assume that we as programmers
‫are gonna make errors.
‫And so it's always best to have a central place like this
‫to handle all promise rejections
‫like a last safety net, all right?
‫Now, if we really have like some problem
‫with the database connection, like we have in this example,
‫then our application is not gonna work at all.
‫And so all we can really do here
‫is to shut down our application, all right?
‫So to shutdown the application, we use process.exit.
‫And we actually already used that before
‫in that script where we imported all the data
‫into the database from the JSON file, remember?
‫So process.exit and then in here,
‫we can actually pass a code.
‫And the code zero stands for a success
‫and one stands for uncaught exception.
‫And so that's the one that's usually used here, all right?
‫So usually, you will always see it like this.
‫And let's just add like a log here, console.log
‫unhandler the rejection,
‫something like this.
‫So you see, I really like this, this one here.
‫Just letting this are node...
‫Not really user but our log
‫that we're shutting down, all right?
‫And so now, you see that the app actually crashed.
‫And so that's because of this process.exit here, all right?
‫Now, there is just one problem with the way
‫we implemented it right now
‫and that is, that the way we implement it here
‫so just process.exit is a very abrupt way
‫of ending the program because this will just immediately
‫abort all the requests that are currently still running
‫or pending and so that might not be a good idea, okay?
‫And so usually, what we do is to shutdown gracefully
‫where we first close the server and only then,
‫we shut down the application, okay?
‫So let's...
‫Before we do that, we need to save the server here
‫basically to a variable, okay?
‫And so the result of calling app.listen is a server
‫and to now, on that server, we can then say server.close
‫which will, as the name says, close the server
‫and then after that's done,
‫it will run this callback function that we passed into it
‫and so it's only here,
‫where we then shut down the server, okay?
‫And so by doing this, by doing server.close,
‫we give the server, basically time to finish all the request
‫that are still pending or being handled at the time,
‫and only after that, the server is then basically
‫killed, all right?
‫So when we give it a safe, it's not gonna look
‫exactly the same because, (laughs) yeah,
‫we're like the only ones that really accessing
‫this application but in the real world scenario,
‫we should always do it like this, okay?
‫And of course, that's not really ideal
‫that the application crashed, right?
‫Because right now, of course, the app is not running,
‫it's not working at all, right?
‫And so usually, in a production app on a web server,
‫we will usually have some tool in place
‫that restarts the application right after it crashes,
‫or also some of the platforms that host node.js
‫will automatically do that on their own, okay?
‫Because, of course, we don't wanna leave the application
‫hanging like this forever.
‫So that's not useful either, all right?
‫And so basically, this is how you handle
‫unhandled rejected promises.
‫So again, basically, we are listening
‫to this unhandled rejection event,
‫which then allows us to handle all the errors
‫that occur in asynchronous code
‫which were not previously handled.
‫But now, you might ask, what about the synchronous code?
‫Where are we gonna handle that?
‫And the answer to that lies, as you can imagine,
‫in the next video.