Now that we implemented our MongoDB logic,
let's wrap up this course section
by adding some error handling to the API routes.
Because data is also something you should know how to do.
When you run server side code,
things don't always go right.
And at the moment we assume that everything works.
Like here.
When we store a newsletter.
When we do that,
we check the request method,
check that it's a post method.
And if it is, we basically just validate the input.
That's one case
where we send back an error status code if it's not valid.
But for working with the database we just assume that
everything works.
And that's unrealistic.
Things won't always work.
Connecting to the database could fail
or even if we are connected,
inserting data could fail for whatever reason.
Because the database servers went down temporarily
just when we tried to insert data.
Things can fail.
No matter how unlikely that might be.
So how do we deal with that then?
Well, since I'm using a single weight here,
we can use, try catch
to try certain operations, catch errors
and then send back a response if things go wrong.
And here I actually wanna work with
two different try catch blocks.
I wanna try connecting.
And if that fails, I wanna send back an error.
But if it succeeds, I want to try this code.
So inserting, I wanna try that.
And if that fails,
I want to send back an error,
a different error.
And I then also still wanna close the open connection.
And to do this in an elegant way
I'll work with some helper functions.
For that I'll add a new function,
which will name, connect database.
The name is up to you of course.
And this function here,
will just hold this code for establishing a connection.
So I'll put that in here,
and then just return the client.
And I'll add another of function,
which I'll name, insert document,
where I expect to get access to the client.
And where I get the document that should
be inserted as parameters.
And inside of insert document,
I then wanna run this code here.
So copy that into insert document.
And of course in order to use a weight
there should be an async function
and this here should be an async function as well.
Connected database.
Now, with that done down here in our main handler function,
I get the client by calling connect database
and then I will call insert document,
pass my client as a first argument.
And that document here as a second argument.
Now I wanna await connect database
because it is a async function
so it returns a promise
and we need to wait for disconnection to be established.
And for the same reason
we also want to await inserted document
because that's also an async operation.
Now with that outsourced to make this code
a bit more readable,
I will wrap connecting
with try and catch potential errors here.
And I'll then do the same for inserting here.
I'll also wrap this with try and catch errors here.
Now I wanna call a client close
if we did connect successfully,
but we failed to insert.
So I wanna call client close instead
of this try block here as well.
And to make sure that client is available here,
I'll set it as a variable here,
and set it to a value in the first try block.
And if we make it past this block,
client will be the connected database.
So calling close will work then.
And then here we got the different errors.
If we fail to connect,
I wanna send back a response
where I set the status code to 500.
Which indicates that something went wrong on this server.
Which clearly is the case here.
And I'll send back a object as json
which has a message where I say,
connecting to the database failed.
And if that failed,
I don't wanna continue with the other code.
I don't want to continue with this try-catch block.
And I certainly don't want to send back this response.
Eventually,
hence here all returned in
to prevent fervor function execution.
I'll do something similar here if we fail to insert.
I'll copy that code
but I'll set the message to, inserting data failed.
And that's how we can handle errors here.
If we make it past both try-catch blocks.
So if we don't go into any of these catch blocks,
to be precise,
we will still send back that success response.
Now to check whatever didn't works.
We can temporarily break disconnect database function
by using incorrect credentials
like a username that doesn't exist.
We save that
and I go back to the newsletter part here.
If I try to sign up with some dummy newsletter
we see that we get back an error here,
in the network tab we also see it.
We see that we got back a response
with a status code of 500
where the message we get is connecting
to the database failed.
Now, as mentioned before, we don't have any feedback
on the user interface and you might of course
want to add such feedback also
for the loading states and on.
I just didn't focus on this at the moment
because I want to thoroughly dive into API routes.
And there we can see that our error handling works.
If I go back to a correct username
and we try that same request again,
I still get an error.
Inserting data failed is what I get now.
That's unintended but it's good to know.
Let's see what went wrong there.
And the problem here is a simple error I made
in this extra inserts document function.
I'm accepting client and document,
while, I should be using that document
for inserting data.
Instead of having my hard coded document there
as I had before
where I referenced user email,
which is just not available
I should be using the document we get as a parameter.
So still nice to see that this error handling also worked.
But with that fixed,
if we now try this again.
Now that's looking better.
We got a success response here and it works.
So that's how we can add error handling here.
Now let's also add it to the other API route.