Search code examples
javascriptpromisebluebird

Manage async operations in a sequential flow with bluebird


First off, I am not gonna deny that I am very new to promises and trying to get better at managing promises in my new Node.js app. I am using bluebird based on what I heard from friends and community. Here is a scenario:

The app has a sign up flow, a typical use case where in the following events have to occur in order to sign up a new user:

  1. Check if a user already exists.
  2. If not, add a new user.
  3. Send a verification email.

I do have 3 separate functions addressing each of the above steps.

Now here is what I have come up with using promises flow...but somehow am not convinced with the code below:

user.isExistingUser(email)
        .then((successData) => {
            if(successData && successData.length === 0) {
                user.signUp(signUpInfo)
                .then((successData) => {
                    emailService.sendVerificationEmail(recipientInfo)
                    .then((successData) => {
                     res.json(responseUtility.getApiResponse(successData));
                    })
                    .catch((errorObj) => {
                        res.json(responseUtility.getApiResponse(null, null, errorObj));
                    });
                })
                .catch((errorObj) => {
                    res.json(responseUtility.getApiResponse(null, null, errorObj));
                });
            } else {
                res.json(responseUtility.getApiResponse(null, [{
                    param: 'email',
                    msg: 'An account already exists with this email'
                }], null));
            }
        })
        .catch((errorObj) => {
            res.json(responseUtility.getApiResponse(null, null, errorObj));
        });

As you may see the code seems a bit too long and can become a bit tricky to track. Can some bluebird expert here help with with a better or more readable code?


Solution

  • You should make better use of chaining. Always return promises from your functions that do something asynchronous.

    user.isExistingUser(email).then(successData => {
        if (successData && successData.length === 0) {
            return user.signUp(signUpInfo).then(() => {
    //      ^^^^^^
                return emailService.sendVerificationEmail(recipientInfo);
    //          ^^^^^^
            }).then(successData => {
                res.json(responseUtility.getApiResponse(successData));
            });
        } else {
            res.json(responseUtility.getApiResponse(null, [{
                param: 'email',
                msg: 'An account already exists with this email'
            }], null));
        }
    }).catch(errorObj => {
        res.json(responseUtility.getApiResponse(null, null, errorObj));
    });