Pyae Phyoe Shein
Pyae Phyoe Shein

Reputation: 13787

How to use promise chaining in my current coding in NodeJS

I'm very new in NodeJS and following is my coding and you guys can catch up what is the purpose of that coding. My code checker told me that to use promise chaining and that can use a single .catch() at the end of a chain when I use that. Please let me know how to convert my current coding by using promise chaining.

jobSeekerService.findJobSeekerUserByEmail(user.username).then(function (jsFromDb) {
    if (jsFromDb) {
        jobAlertsService.findJobAlertWithCategoriesByJobSeekerId(jsFromDb.jobSeeker.id).then(function (subscription) {
            if (subscription.categories && subscription.categories != 0) {
                res.redirect(redirectUrl);
            } else {
                res.redirect('/subscriptions');
            }
        }, function (err) {
            winston.error('applications.controller findJobAlertWithCategoriesByJobSeekerId : %s', err);
            res.send(500);
        });
    } else {
        res.redirect(redirectUrl);
    }
}, function (err) {
    winston.error('applications.controller findJobSeekerUserByEmail : %s', err);
    res.send(500);
});

Upvotes: 0

Views: 83

Answers (2)

Paulooze
Paulooze

Reputation: 1237

You can/should use promises like this

promise.then(function(res) {
  /* do whatever you want with the res */
  return promise2(foo);
}).then(function(data) {
  /* data from promise2 are here */
}).catch(function(err) {
  /* err parameter contains error from reject() */
});

You can use .then() infinite number of times, but catch() can be called just once for error handling (it will contain error from the corresponding reject() in the Promise() object.

Edited the example for better understanding.

Upvotes: 1

Bergi
Bergi

Reputation: 664395

You might use

jobSeekerService.findJobSeekerUserByEmail(user.username).then(function (jsFromDb) {
    if (jsFromDb)
        return jobAlertsService.findJobAlertWithCategoriesByJobSeekerId(jsFromDb.jobSeeker.id).then(function (subscription) {
            if (subscription.categories && subscription.categories != 0)
                return redirectUrl;
            else
                return '/subscriptions';
        }, function (err) {
            winston.error('applications.controller findJobAlertWithCategoriesByJobSeekerId : %s', err);
            throw err;
        });
    else
        return redirectUrl;
}, function (err) {
    winston.error('applications.controller findJobSeekerUserByEmail : %s', err);
    throw err;
}).then(function(url) {
    res.redirect(url);
}, function() {
    res.send(500);
});

The important things for chaining are those returns. Admittedly, this solution is not very exciting and much of an improvement over what you already have. The problem is that distinguishing error conditions always requires nesting with promises. You might be able to avoid that by finding the name of the respective method within the error object (e.g. in the stack trace) so that you can combine the error handler into a generic one.

A second thing you could do is to flatten the success handler for the category search, but I'm not sure whether it's worth it. With both of these, your code would now look like this:

jobSeekerService.findJobSeekerUserByEmail(user.username).then(function (jsFromDb) {
    return jsFromDb
      ? jobAlertsService.findJobAlertWithCategoriesByJobSeekerId(jsFromDb.jobSeeker.id)
      : {categories: 1};
}).then(function (subscription) {
    return (subscription.categories && subscription.categories != 0)
      ? redirectUrl
      : '/subscriptions';
}).then(function(url) {
    res.redirect(url);
}, function(err) {
    winston.error('applications.controller: %s', err);
    res.send(500);
});

This also has the benefit that it will catch exceptions from subscription being null or so.

Upvotes: 1

Related Questions