0

I have a promise chain that is currently running with very basic error handling. If a step fails, the subsequent steps will not run. I want to be able to continue the promise chain at a later time if there is a failure, and it should start from where it left off.

This is what my current code looks like:

// controller.js
var failure = false;
QueryFactory.step1()                      // Step 1
   .then(function(msg){
      if(failure == false){
        console.log("Finished Step 1");
        return QueryFactory.step2();
      }
   }, function(err){
      console.log(err);
      failure = true;
   })
   .then(function(msg){                   // Step 2
      if(failure == false){
         console.log("Finished Step 2");
         return QueryFactory.step3();
      }
   }, function(err){
      console.log(err);
      failure = true;
   })
   .then(function(msg){                   // Step 3
      if(failure == false){
         console.log("Finished Step 3");
      }
   }, function(err){
      console.log(err);
      failure = true;
   })

And my factory looks like this:

// QueryFactory.js
step1 = function(){
   var deferred = $q.defer();
   $http.post('/task', {step_num: 1})
      .then(function(data)){
         deferred.resolve(data);
      }, function(err){
         deferred.reject(err);
      });
   return deferred.promise;
}
// step2 and step3 are similar

But perhaps there is a better way of writing this to allow for modularity? Say step2 were to fail, how can I design a way so that a user can click a button to later continue the chain from step2?

Kangze Huang
  • 351
  • 7
  • 22
  • Your "chain" doesn't pass any data from any step to the following step. Also, they will all execute one after the other, regardless of "success" or "failure". – Amit Apr 13 '16 at 18:09
  • So how do you recommend I do this correctly? – Kangze Huang Apr 13 '16 at 18:13
  • 1
    First of all, avoid the [deferred antipattern](http://stackoverflow.com/q/23803743/1048572)! – Bergi Apr 13 '16 at 18:21

1 Answers1

1

Have a look at the difference between .then(…).catch(…) and .then(…, …). In your case, by passing the second callback to then, you'd eventually step over the current step instead of continuing where you left off. What you are looking for is

QueryFactory.step1()
.then(function(msg) {
    console.log("Finished Step 1 without error");
    return msg;
}, function(err) {
    console.log(err);
    …
}).then(function() {
    return QueryFactory.step2();
}).then(function(msg) {
    console.log("Finished Step 2 without error");
    return msg;
}, function(err) {
    console.log(err);
    …
}).then(function() {
    return QueryFactory.step3();
}).then(function(msg) {
    console.log("Finished Step 3 without error");
    return msg;
}, function(err) {
    console.log(err);
    …
}).then(function(res) {
    console.log("everything is finished");
}).catch(function(err){
    console.error("something bad happened", err);
});

(Alternatively you can use a plain .catch instead of the then with the callback that tells you whether a step finished without error, if you don't need those logs)

Now, what are these in the code? It's for your requirement

I want to be able to continue the promise chain at a later time if there is a failure

In the sections, you will need to handle the error, and return a promise for error-free result of the step that failed, e.g. by retrying. This promise would only settle at that "later time" - you can wait for a user confirmation of the error, a timeout, or whatever you want.

Once that promise you returned from the error callback settles, the chain will continue.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375