2

I have an issue where I may need to jump out of the whole promise chain because of some value or take two paths based on a value.

How best do you do that?

Here is the first scenario where I would like to just jump out of the whole chain. I just want to give them a message.

      DB_WorkIssues.info().then(function (details) {
     if (details.doc_count == 0 && details.update_seq == 0) {
        showMsg("This device has no local data on it and no access to the Server, please come back when you are online.")
     }  jump out here, no need to do the next set.
     else
     return;     Continue on as the values are valid.
      }).then(function () {
     return ajaxCallForJson(URI_LookupTables);
      }).then(function (json) {
     return callBulkDocLoad(DB_LookupTables, json);
      }).then(function () {
     return loadCategoriesDDL();
      }).then(function () {
     return loadEquipmentDDL();
      }).catch(function (err) {
     showMsg("Error in defineDBs: " + err);
      });

In the 2nd scenario, I may want to take one path if the values are one thing and another if the values are another. But I still want the chains to work with the first promise. Something like this:

      DB_WorkIssues.info().then(function (details) {
     if (details.doc_count == 0 && details.update_seq == 0) {

     Take this path.
          return;
          }).then(function () {
         return ajaxCallForJson(URI_LookupTables);
          }).then(function (json) {
         return callBulkDocLoad(DB_LookupTables, json);
          }).catch(function (err) {
         showMsg("Error in defineDBs: " + err);
          });

     }  
     else
     {

     Take this path instead

         return;
          }).then(function () {
         return loadCategoriesDDL();
          }).then(function () {
         return loadEquipmentDDL();
          }).catch(function (err) {
         showMsg("Error in defineDBs: " + err);
          });
    }

Thanks.

Here is what I was thinking after looking at the answer where I do the second promise always and only do the first in some cases.

    DB_WorkIssues.info().then(function(details) {

      // promise variable , defined in conditional
      var promise;

    Would I set the promise to some default value, in case the following test fails

      if (details.doc_count == 0 && details.update_seq == 0) {
        // return this promise
        promise = ajaxCallForJson(URI_LookupTables).then(function(json) {
          return callBulkDocLoad(DB_LookupTables, json);
        });

      }
      return promise;

    }).then(function () {
       return loadCategoriesDDL();
    }).then(function () {
       return loadEquipmentDDL();
    }).then(function () {
       return loadLocationsDDL();
    }).catch(function (err) {
       showMsg("Error in defineDBs: " + err);
    });

Is that how I could do it?

Thanks.

tshad
  • 335
  • 2
  • 4
  • 18
  • 2
    if/else is a good way to choose from two paths - the pseudo code (clearly not correct code) makes it difficult to understand what you are trying to achieve – Jaromanda X Apr 12 '17 at 23:41
  • You can throw an error for your first scenario (or return a rejected promise) – MinusFour Apr 12 '17 at 23:55
  • 1
    When you have programmatic logic that determines what comes next, you want to branch, not chain. That splits your logic into a separate branch of execution based on some conditional test. A pure chain is meant to be sequential. You could hack it to skip the rest of the chain by returning a fake error that you could somehow discern from a real error, but that's a hack. The right model is to branch your chain into a separate sub-chain based on your conditional logic and not try to use just one long chain for multiple logic flows. – jfriend00 Apr 13 '17 at 00:23
  • Possible duplicate of [How to properly break out of a promise chain?](http://stackoverflow.com/q/29499582/1048572) – Bergi Apr 13 '17 at 17:13

2 Answers2

2

I think this is a skeleton that represents what you're going for. Promises are incredibly powerful and worth studying. I tried to add helpful comments but I suggest playing around with the code and understanding what's going on.

// Six named promise-creators. When called with (x), will create a promise
// which waits 200ms and then logs and resolves with (x). 
// These could represent any asynchronous operation.
const p1 = p2 = p3 = p4 = p5 = p6 = 
  (x) => {
    const p = new Promise((resolve, reject) => {
      setTimeout(() => {resolve(x); console.log(x)}, 200)
  });
  return p;
}

// A function which, when called, will execute first promise chain.
const first_steps = () => 
  p1(1)
    .then(result => p2(2))
    .then(result => p3(3))

// A function which, when called, will execute second promise chain.
const second_steps = () => 
  p4(4)
    .then(result => p5(5))
    .then(result => p6(6))

// When true, this prints numbers 1-6.
// When false, only prints numbers 4-6.
if (false) {
 console.log(first_steps().then(second_steps));
} else {
 second_steps();
}
Kenan Banks
  • 207,056
  • 34
  • 155
  • 173
0

Seems to me you have extra sets of then() and your if() would determine which promise to return something like:

DB_WorkIssues.info().then(function(details) {

  // promise variable , defined in conditional
  var promise;

  if (details.doc_count == 0 && details.update_seq == 0) {
    // return this promise
    promise = ajaxCallForJson(URI_LookupTables).then(function(json) {
      return callBulkDocLoad(DB_LookupTables, json);
    });

  } else {
    // or this promise
    promise = loadCategoriesDDL().then(function() {
      return loadEquipmentDDL();
    });
  }

  promise.catch(function(err) {
    showMsg("Error in defineDBs: " + err);
  });

  return promise;

})
charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • That is what I am looking for. I guess there was a third way. Using the above one, what I want to do is not an either/or but if the test does not fail, I do the top promise and I also want to do the 2nd promise. If the test fails, I only want to the 2nd promise. The second promise chain could be 10 thens. Would I then just put the 2nd promise after the original promise (DB_WorkIssues.info..) as a then. – tshad Apr 13 '17 at 00:30
  • not very clear what you are asking... note that you can throw an error that has data associated...and use catch to return a new promise chain – charlietfl Apr 13 '17 at 00:33
  • also might consider wrapping the different branches in functions to keep branching more readable – charlietfl Apr 13 '17 at 00:34
  • What I was thinking about was something like what added to my question? If that is valid, what would I set the promise incase I don't do the ajax section? – tshad Apr 13 '17 at 00:39
  • if you don't need that step, return anything, doesn't have to be a promise – charlietfl Apr 13 '17 at 01:24
  • You probably will want to `return` the `promise.catch(…)` result, not the `promise` itself. And with that, you could just chain the `catch` after the outer `then`, and omit the `promise` variable completely. – Bergi Apr 13 '17 at 17:15