3

With the following code, when I reject the promise, I see the first console.log but I also see the second console.log. This is expected since the rejection only affects the next "then()".

The question is, is there any operator equivalent to a "break" in a loop, so that you can jump off the chain? The fast answer would be yes, with a non-catched reject() or throw(), but both approaches will send an error message to the console (will they stop the whole code execution?)

So the question is, can it be done "cleanly"?

*My first assumption was that by catching the reject/error this would do the trick, but it is not the case

Promise.resolve()
.then(function(){
  do stuff
  return Promise.resolve();
})
.then(function(){
  if (a === 'this')
    return Promise.resolve();
  else
    // is there any "break" equivalent here?
    return Promise.reject();
})
.then(function(){
  console.log('seen if not rejected');
},function(){
  console.log('seen if rejected');
})
.then(function(){
  console.log('seen all the time');
});
GWorking
  • 4,011
  • 10
  • 49
  • 90
  • `ReferenceError: a is not defined(…)` – Cory Danielson Aug 18 '16 at 15:20
  • 1
    @CoryDanielson That isn't the problem. They're asking why returning a rejected promise does not end the chain. – Mike Cluck Aug 18 '16 at 15:22
  • @CoryDanielson please see that as pseudo-code – GWorking Aug 18 '16 at 15:22
  • 1
    because youre continuing to call `.then()`. [from mdn](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) **The then() method returns a Promise.** *It takes two arguments: callback functions for the success and failure cases of the Promise.* Your final `.then()` should be in with `stuff` rather than chained again. – Craicerjack Aug 18 '16 at 15:23
  • 1
    It's because you `catch` the rejection in the function where you log `console.log('rejected, end of chain');` – Adam Aug 18 '16 at 15:23
  • 1
    @MikeMcCaughan really this post is specific of AngularJS, which can be confusing for non-angular people (or even for beginners like me) – GWorking Aug 18 '16 at 15:31
  • $q and Promise use essentially the same semantics. If you'd prefer, there are plenty of other duplicates: http://stackoverflow.com/q/16371129/215552, http://stackoverflow.com/q/29853578/215552, etc. – Heretic Monkey Aug 18 '16 at 15:38
  • For a solution, [just](http://stackoverflow.com/a/24663315/1048572) put the `console.log('only executed if not rejected');` right inside the callback with the `stuff` – Bergi Aug 18 '16 at 15:42
  • @MikeMcCaughan, I have edited the question to be more precise in the question, which is now not why it doesn't stop, but how it can be stopped without sending messages to the console – GWorking Aug 18 '16 at 15:52
  • @Bergi is the one with the dupehammer, not me :). Are the answers on the marked duplicate not clear as to how to do this? As an aside, you shouldn't be changing the question if you already have answers to the previous one. That's a "bait and switch" that's frowned upon. – Heretic Monkey Aug 18 '16 at 16:07
  • For the new question, it's probably a duplicate of [How to properly break out of a promise chain?](http://stackoverflow.com/q/29499582/1048572) (also see the questions linked from there) – Bergi Aug 18 '16 at 16:13

3 Answers3

1

As you pass a second argument (onRejected function) to then method, the rejection is actually caught. And it returns a promise too, so you can continue chaining.

If you remove the onRejected function in your third then, you will see an uncaught exception in console, for example:

Promise.reject()
  .then(function(){
    console.log('resolved');
  })
  .then(function(){
    console.log('you cannot see me');
  })

// Uncaught (in promise)

And yes, you can catch the exception, if it's not caught by onRejected:

Promise.reject()
  .then(function(){
    console.log('resolved');
  })
  .catch(function(){
    console.log('you can see me');
  })

// you can see me


Promise.reject()
  .then(function(){
    console.log('resolved');
  }, function(){
    console.log('rejected');
  })
  .catch(function(){
    console.log('you cannot see me');
  })

// rejected

Regarding my experiences, in real business scenario we usually want to separate irrelevant logic. So we would caught the rejection in onRejected, do something, then throw the exception to catch method (either in itself or in chaining then):

Promise.reject()
  .then(function(){
    console.log('resolved');
  }, function(e){
    console.log('rejected');
    throw e
  })
  .catch(function(){
    console.log('you can see me');
  })

// rejected
// you can see me
Leo
  • 13,428
  • 5
  • 43
  • 61
1

Both .then(success, error) callbacks return promises.

That is:

Promise.reject()

.then(function () {
  // won't be called, as above promise is rejected
}, function () {
  // will be called, and returns a resolved promise by default;
  // if you want the next error callback to be called,
  // you need to return a rejected promise or to throw an error
})

.then(function () {
  // 1: called if above .then returns a resolved promise
}, function () {
  // 2: called if above .then returns a rejected promise or throws an error
})
sp00m
  • 47,968
  • 31
  • 142
  • 252
-1

It's because you catch the rejection. The two block below are equivalent:

example1

var stuff = function () {

};
var doStuff = function () {

};
var a = 'notThis';

Promise.resolve()
    .then(function () {
        doStuff();
        return Promise.resolve();
    })
    .then(function () {
        if (a === 'this')
            return Promise.resolve();
        else
            return Promise.reject();
    })
    .then(function () {
        stuff();
    }, function () {
        console.log('rejected, end of chain');
    })
    .then(function () {
        console.log('only executed if not rejected');
    });

example2

var stuff = function () {

};
var doStuff = function () {

};
var a = 'notThis';

Promise.resolve()
    .then(function () {
        doStuff();
        return Promise.resolve();
    })
    .then(function () {
        if (a === 'this')
            return Promise.resolve();
        else
            return Promise.reject();
    })
    .then(function () {
        stuff();
    })
    .catch(function () {
        console.log('rejected, end of chain');
    })
    .then(function () {
        console.log('only executed if not rejected');
    });
Adam
  • 4,985
  • 2
  • 29
  • 61