Now we made huge progress,
and we get the general sign up
and authentication flows implemented,
still there is room for improvement.
For example, we have no validation,
and we show no validation errors to the user
if we enter incorrect data here
or if we have deviating email addresses here
when we sign up, so that's something we wanna add.
But before we do that,
I wanna come back to error handling in general.
We did add the error-handler middleware
a couple of minutes ago.
But this middleware, which is executed by Express
automatically if an error occurs, has a flow.
Yes, Express will execute it automatically
if some error occurs in any other middleware.
But unfortunately, Express ignores errors
that are occurring inside of asynchronous operations.
So if I await the user sign up here
and inside the signup method or some other function called
inside of the sign up method; something goes wrong,
the Express middleware handler will not become active.
Therefore, we have to handle this manually,
and we learned how we can do this
early in the course as well: with help of try catch.
Try catch allows us to implement our own error handling,
and it allows us to try some operation.
And we can use try catch when we use async await
to then catch a potential error,
which we receive as a parameter value here,
in case this operation
or some nested operation in there goes wrong.
And then here in the catch case,
to use the default Express error handling middleware,
what we can do is we can use
that third parameter value, this "next" function,
which we always get in all our middleware functions,
and our controller actions here are
just middleware functions in the end.
And we can call next here in catch,
and pass the error to it,
and then either return this
or return thereafter, doesn't matter.
So that's the next line doesn't execute
because when we pass an error to next
and we execute next with that error,
the default error handling middleware will become active,
and in our case, that middleware will
then render this 500 template.
And then I don't wanna redirect in addition to it,
which is why we have to return thereafter
so that this code doesn't execute.
But it's this kind of custom error handling logic
that we wanna add to all the parts
in our code that could possibly fail.
For example, here when we get a user with the same email;
I wanna try this:
catch the error here
and call next error if that fails.
So here I call next error then if that fails,
and then return thereafter.
Because if that fails,
we don't wanna execute any of our code in this action.
And now with this approach, we just would face one problem:
The existing user constant now is scoped to this try block.
You'll learn about variable scoping
before in this course as well,
and it basically means that a variable
or constant is only available inside of the block
of curly braces in which it is defined;
in this case, inside of try.
But I wanna use existing user thereafter
and to make it available thereafter.
We simply have to define it
as a variable in an outer block,
and then assign a value in the inner block;
that is allowed, you can access variables
that are scoped to an outer block
from inside the inner block;
the other way around doesn't work though,
which is why we can solve this problem like this,
and then handle this potential error.
And with that, we also improve our log in function here.
We could add more error handling
but comparing the password, actually shouldn't fail here.
So therefore, that's the only error handling
I wanna add here in this case.
But with that, we improved our functions
to add better error handling.
With that done, we can now work on validating the user input
and showing some feedback to the user.
If, for example, different email addresses were provided.