My web agency, Tech Made has been developing MERN Stack web application to manage the growing student body club life for one of our clients, Make School Product College of Dominican University. The beta launch is about to happen and after some user testing here, the system may open up for any institution to use to better manage their student clubs. I’ll soon write more blog posts on the Clubs App.
Today, as the title says, we’re reviewing a cool refactor I recently implemented in the codebase of the Clubs App monolithic backend Node API. Before I dive into the technical details of my code refactor, I’d like to give you some context as to why. I already had my project working just fine so this was not a premature refactor/optimization. During the time of development, I needed to ship fast so I didn’t want to waste even 30 minutes trying over optimize when I knew I could write not the most dry code, but get it to work. I threw it on my Trello backlog and now here we are.
Let’s dive in. I was using JWT tokens stored in the session for user authentication. I had certain routes in my back end that only a user logged in should be able to do, some routes were only meant for club leader users, and some were meant for admins only. So each of these routes would first trigger the middleware to check for a user. I had 3 different authentication checking functions, called checkAuth, checkLeader and checkAdmin. All 3 of them damn near did the same thing to look at the jwt token, get the user id, find the user and continue with what was next in the route or else return an error. The only difference in checkLeader and checkAdmin was before setting req.user and returning next(), I checked if the user.type property was leader or admin, that is all. One line for like 20 extra lines of code in each function!
Here’s what the code looked like and what I refactored it into (The order of new and old code are in reverse order because of GitHub Gists ordering.)
So you can see in the old_checkAuth.js file there’s tons of repeated code happening. But what’s going on in the file below, new_checkAuth.js?
Allow me to walk you through this process of my refactor and finally fucking understanding async/await.
So at first, I legit just tried to get rid of all the code in checkLeader and checkAdmin. Then, simply calling checkAuth function from them and trying to access req.user to check their type. Once ran, my middleware threw a Reference Error, it did not know what req.user was. So calling another function from my other function wasn’t allowing me to keep the scope of the user variables. After some thinking, I decided to try and make the original function being called, checkAuth, return a Promise.
Finally, I realized I need to wait for that function to finish before executing the next line of code. Welcome, async/await! You can see in my new code how I made the checkLeader function asynchronous by adding the term async in front of function. Then on the checkAuth function call line I set user equal to whatever the function returns and I add await in front of it. So lessons learned here.
It’s just a more elegant syntax of getting the promise result than
promise.then, easier to read and write.
Await must only be used within an async function.
If we try to use
await in non-async function, there would be a syntax error, you can’t async a regular function, you just can’t.