0

I'm using Bookshelf.js, a Promise-based ORM module, to perform a couple database lookups. Given a key that a user provides, I need to determine if the key matches a record in one of two tables. If I find it in the first table, I need to return that record. However, if I don't find it in the first table, I need to look in the second table. Basically, I need to conditionally execute a then block. How do I accomplish this using promises? Here's what I currently have, which is very messy, and, in fact, I'm a little unclear about what happens if I call resolve in the first School lookup -- does the second then block execute as well?

exports.findTargetRecord = function(code){

    return new Promise(function(resolve, reject){
        Schools
        .query({ where: { code: code }})
        .fetchOne()
        .then(school => {
            if(school) return resolve(school);
            return Organizations
                    .query({ where: { code: code }})
                    .fetchOne();
        })
        .then(org => {
            if(org) return resolve(org);
            resolve(null);
        })
        .catch(err => reject(err));
    });
};

Is there a cleaner way to write this?

user2719094
  • 1,611
  • 5
  • 26
  • 36

2 Answers2

2

You can just keep whole else logic inside then block:

exports.findTargetRecord = function(code){

    return new Promise(function(resolve, reject){
        Schools
        .query({ where: { code: code }})
        .fetchOne()
        .then(school => {
            if(school) return resolve(school);
            return Organizations
                    .query({ where: { code: code }})
                    .fetchOne()
                    .then(org => {
                        if(org) return resolve(org);
                        resolve(null);
                    })
        })
        .catch(err => reject(err));
    });
};

Furthermore your code could be rewriten (shorter version) like this:

exports.findTargetRecord = function(code){
    return Schools
            .query({ where: { code: code }})
            .fetchOne()
            .then(school => {
                if(school) return school;
                return Organizations
                        .query({ where: { code: code }})
                        .fetchOne();
            })
            .catch(err => reject(err));
madox2
  • 49,493
  • 17
  • 99
  • 99
2

Use promises as proxies and a regular if:

exports.findTargetRecord = function(code){

  const school = Schools.query({ where: { code: code }}).fetchOne();
  school = school.then(school => 
    school || Organizations.query({ where: { code: code }}).fetchOne())
  return school;
}

Or with coroutines which bluebird supports (bluebird ships with bookshelf):

exports.findTargetRecord = Promise.coroutine(function*(code) {
   var school = yield Schools.query({ where: { code: code }}).fetchOne();
   if(school) return school;
   return Organizations.query({ where: { code: code }}).fetchOne();
});
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • Thanks, this is more like what I was looking for. It's still not super clean or easy to read, but it's the most different from what I currently have which gives me some options to work with. – user2719094 Sep 07 '16 at 19:07