Is my implementation of async await the most efficient method to handle asynchronous operations in my code?

Struggling to implement and grasp async await functions in my login example, I'm uncertain if my code is the most optimal, elegant, and clean. I especially have doubts regarding error handling, and how to best utilize const and functional programming principles. I would greatly appreciate any feedback or opinions!

app.post('/', async (req, res) => {


    try {

        const { email } = req.body.email; // using destructuring

        const foundUser = await User.findOne({email: email});

        // Check if user exists
        if (!foundUser) { // return null if not found
            throw res.status(404).json({error: 'User not found'});
        }

        // Validate user password
        if (!bcrypt.compareSync(req.body.password, foundUser.password)) {
            throw res.status(404).json({error: 'Password does not match'});
        }

        const token = jwt.sign( // generate token
            {
                user: foundUser 
            },
            SEED,
            {
                expiresIn: (60 * 60)
            }
        );

        res.status(200).json({ // send response
            token: token,
            user: foundUser
        });

    } catch (error) { // handle errors

        res.status(404).json(error);

    }
}

THANKS

Answer №1

There are a few issues with your code that need to be addressed:

  1. You're trying to send multiple responses. First, you use res.status(404).json(...) and then you catch the exception and use res.status(404).json(e) again. This approach is incorrect. If you intend to send a response, simply return without throwing an exception. Alternatively, throw the exception without sending a response, and handle the error response within the catch block.

  2. Additionally,

    throw res.status(404).json({error: 'No match'});
    sends the response and then throws whatever .json() returns, which may not be an error object as expected.

In my opinion, it's better to consolidate error response handling within the request handler. This prevents the issue of sending multiple responses and ensures a clearer flow within the handler.

To achieve this, I prefer to throw a custom error with a specified message or status, and then catch and handle all possible errors in one place. Below is an example implementation of a reusable Error class that allows for throwing custom errors with specific status values.

// Reusable error class with status property
class MyError extends Error {
    static sendError(res, e, status = 500) {
        if (e instanceof MyError) {
            e.sendError(res);
        } else {
            res.sendStatus(status);
        }
    }
    
    constructor(msg, status = 500) {
        if (!(this instanceof MyError)) {
            return new MyError(msg, status);
        }
        super(msg);
        this.status = status;
    }
    
    sendError(res) {
        res.status(this.status).send(this.message);
    }
}

Here's how you can integrate this error handling approach into your code:

app.post('/', async (req, res) => {
    try {
        const { email } = req.body.email; // Destructuring

        const foundUser = await User.findOne({ email: email });

        if (!foundUser) {
            throw MyError('User not found', 404);
        }

        if (!bcrypt.compareSync(req.body.password, foundUser.password)) {
            throw MyError('Password does not match', 404);
        }

        const token = jwt.sign(
            { user: foundUser },
            SEED,
            { expiresIn: 3600 }
        );

        res.status(200).json({
            token: token,
            user: foundUser
        });
    } catch (e) {
        console.log(e);
        MyError.sendError(res, e);
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Generate dynamic routes in Next.js only when needed

I'm currently working on a project using NextJS to create a frontend for a database that contains thousands of products, with the expectation of significant growth. The site/products/ route is functioning well, but I wanted to add a route to view indi ...

When using @testing-library/react (rtl), the 'waitFor' function achieves success even without the need for the 'await' keyword

waitFor() is causing my test to fail while waitFor() (without await) makes it pass. The official documentation states: Async methods return a Promise, so you must always use await or .then(done) when calling them. (https://testing-library.com/docs/guide ...

What could be the reason for jQuery not functioning properly as needed?

function toggleDisplayingRooms(nameSelect){ if(nameSelect){ firstroom = document.getElementById("firstroom").value; secondroom = document.getElementById("secondroom").value; thirdroom = ...

Steps to design a unique input radio button with embedded attributes

In my current project, I am utilizing react styled components for styling. One issue that I have encountered is with the text placement within a box and the need to style it differently when checked. What have I attempted so far? I created an outer div a ...

`What purpose does the data-view attribute serve in Durandal JS?`

While experimenting with the Durandal JS starter kit application, I happened to view the page source in Mozilla browser and noticed the following. <div class="" data-view="views/shell" style="" data-active-view="true"> </div> I couldn't ...

What is the best way to establish a limit on the number of characters that can be entered into an input field in a React form?

Currently, I am creating a tool to check the strength of passwords based on their length. However, I am unsure of how to precisely determine if a password falls within specific length ranges such as "between 5 and 10 characters" or "between 20 and 30 cha ...

Transition within Vuejs moves forwards and backwards, with a unique feature that allows it to skip directly to

I am in the process of developing a slider element that consists of only 2 items. My goal is to ensure that these items smoothly slide back and forth to the left and right when I click on the back or next button. While everything functions correctly when I ...

Navigating Angular QueryList through loops

I am currently trying to gather all the images in my component and store them in an array. To achieve this, I am utilizing Angular's @ViewChildren which returns a QueryList of ElementRef: @ViewChildren('img', { read: ElementRef }) images: Q ...

What is the proper method to trigger a re-render of a React functional component with the useEffect

Within my top-level component, I am utilizing a library to determine if a user’s browser is in light or dark mode. This information is then used to set the theme for the application, which includes HTML Canvas elements (it's crucial to note that the ...

Tips for creating a Vue component that triggers the select dropdown to open when the entire div or wrapper is clicked

I have a custom-designed select dropdown with unique symbols for the select arrow. To achieve this look, I've hidden the default select arrow/triangle and placed our symbol on top as an image file. <div class="select-wrapper"> < ...

How can I incorporate dynamic data to draw and showcase graphs on my website using PHP?

I am currently working on a project that requires displaying a graph showing the profit of users per day. Currently, I have implemented code to display a static graph on my page. <script type="text/javascript" src="https://www.google.com/jsapi">< ...

Trouble with Sound during Quickblox Webrtc Audio Calls

I am having an issue with my audio calls. When I make a call to another user, everything seems fine except that I cannot hear any sound when speaking into the microphone. I am only interested in making audio calls. The call is initiated by pressing a butt ...

The error message states: "An attempt was made to destructure a non-iterable object. In order for non-array objects to be iterable, they must have a [Symbol.iterator

I need to call a RTK query endpoint from a function const [getCityCode, { isLoading, error, data, isSuccess, isError }] = useLocationQuery(); const getLocationDetails = async () => { const queryItems = { latitude: lat, longitude: long }; await getC ...

Ordering AngularJS by property name with spaces

While working with the MEAN stack and jade, I encountered an issue with AngularJS when using ng-repeat, ng-click, and orderby to sort columns in a table. Everything was working well until I tried sorting by a column named "To Do" which contains a space. Th ...

The library 'material-ui' does not have a 'withStyles' export available

Here is the content of my package.json file. Everything was working fine until recently when I started encountering this error. "@material-ui/icons": "1.0.0-beta.42", "chartist": "0.10.1", "classnames": "2.2.5", "material-ui": "1.0.0-beta.41", "npm-ru ...

How to retrieve distinct items from an array using Javascript

If I have the following array of objects: const arr = [{ id: 'A', version: 0, name: 'first' }, { id: 'A', version: 1, name: 'first' }, { id: 'B', version: 0, name: 'second&apo ...

Identifying the hashKey and selected option in a dropdown menu

My attempt to set the selected option for the select menu is not working because the data in the ng-model that I am sending has a different $$hashKey compared to the data in the select menu, and the $$hashKey holds the values. <select class="form-contr ...

Identifying text within a paragraph using JavaScript regex, excluding any URLs mentioned

How can I use JavaScript on the client side to find a search term in a paragraph while excluding any matches that are part of a URL? I attempted to use the following regex but encountered an error: "A quantifier inside a lookbehind makes it non-fixed widt ...

Guide for creating a scroll-triggered rotation animation using only JavaScript

Looking to achieve a cool scroll effect with an image that rotates on the X-axis by a specific degree, such as 70deg. The goal is to have the image's rotateX value change to 0deg when it enters the viewport upon scrolling and revert back to 70deg whe ...

What is causing my checkboxes to deactivate other selections?

My checkboxes are causing a dilemma where changing the value of one checkbox sets all others to false. To address this issue, I am considering implementing a solution in my validate.php file that would only update the intended checkbox value. If this appro ...