0

I have a sign-in logic with Express and Mongo. I need to put them into one promise chain and avoid nesting promises.

Here is my code:

    const foundUser = User.findOne({ email: email }).exec();
    const hashedPassword = bcrypt.hash(password, 10);

    return Promise.all([foundUser, hashedPassword])
        .then(arr => {
            const [ user, hashedPassword ] = arr;

            if (user) {
                return res.status(400).json({
                    message: "This email has already occupied."
                });
            };

            const newUser = new User({
                fullName,
                email,
                password: hashedPassword
            });

            newUser.save()
            .then(user => {
                return res.status(200).json({
                    message: `${user.fullName}, you are successfully registered.`
                });
            })
            .catch(err => {
                console.log(err);
                return res.status(500);
            })
        })
        .catch(err => {
            console.log(err);
            return res.status(500);
        });

I tried to use to combine them with Promise.all, but one of my promises depends on the previous one, so I added newUser.save() in my then.

I achieved that async/awaits like this:

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

if (foundUser) {
    return res.status(400).json({
        message: "This email has already occupied."
    });
}

const hashedPassword = await bcrypt.hash(password, 10);

const newUser = new User({
    fullName,
    email,
    password: hashedPassword
});

const user = await newUser.save();

return res.status(200).json({
    message: `${user.fullName}, you are successfully registered.`
});

} catch (err) {
    console.log( err);
    return res.status(500).json({
        message: 'Error'
    })
}

But I wonder is there a way to do it with promises and without nesting. I need to put them on one chain so I can avoid using multiply catches

Liam
  • 27,717
  • 28
  • 128
  • 190
Robert Hovhannisyan
  • 2,938
  • 6
  • 21
  • 43

1 Answers1

1

As @Bergi mentioned in the comment, you can return a promise from your .then callback. Depending on if this returned promise gets resolved or rejected, your .then or .catch next in the chain is called. You can do something like this:

    const foundUser = User.findOne({ email: email }).exec();
    const hashedPassword = bcrypt.hash(password, 10);

    return Promise.all([foundUser, hashedPassword])
        .then(arr => {
            const [ user, hashedPassword ] = arr;

            if (user) {
                return res.status(400).json({
                    message: "This email has already occupied."
                });
            };

            const newUser = new User({
                fullName,
                email,
                password: hashedPassword
            });

            return newUser.save()
        })
        .then(user => {
            return res.status(200).json({
                message: `${user.fullName}, you are successfully registered.`
            });
        })
        .catch(err => {
            console.log(err);
            return res.status(500);
        });

Kiran
  • 340
  • 2
  • 11