JoelSanchez JoelSanchez - 16 days ago 5
AngularJS Question

Angular promises - Chaining reject and resolve channels separately

Situations



If I do this:

cookFood().then(function(food) {
eatFood(food);
});


Whether cookFood rejects or resolves, eatFood will be executed. I don't want that, since I want it to execute only when it resolves, because that's what it was made for, not for handling errors.
Also if I do this:

cookFood().then(function(food) {
return eatFood(food);
}, function() {
console.error('Error coooking food');
return 'FOOD_ERROR';
}).then(function(food) {
return shitFood(food);
}, function(err) {
if (err === 'FOOD_ERROR') {
alert('Looks like there was an error cooking food...');
}
});


I'll never get an alert, because I executed an error handler before. I don't want that, because I want to execute both. Also, "shitFood" will be called if there was an error, something undesirable.

Solutions



I know solutions to both situations. I just think there "has to be a better way".

To the first one:

cookFood().then(function(food) {
eatFood(food);
}, angular.noop);


Now eatFood won't be called with something that's not food. But do I have to use angular.noop every single time I don't want to handle the error (because I will do so later in the chain)?

To the second one:

cookFood().then(function(food) {
return eatFood(food);
}, function() {
console.error('Error coooking food');
return $q.reject('FOOD_ERROR');
}).then(function(food) {
return shitFood(food);
}, function(err) {
if (err === 'FOOD_ERROR') {
alert('Looks like there was an error cooking food...');
}
});


This works as I expect, but I think I shouldn't need to manually reject, because the value handler does not have to manually resolve.

Mostly I'd like to clear any misconceptions I may have, and to be informed of a better way to do this. Thank you.

Answer

If I do cookFood().then(eatFood);, whether cookFood rejects or resolves, eatFood will be executed.

No, that's untrue. eatFood will only be executed when cookFood fulfills. You don't have to pass noop or null or something as the rejection handler to get that behaviour.

cookFood().then(function(food) {
    return eatFood(food);
}, function() {
    console.error('Error coooking food');
    return $q.reject('FOOD_ERROR');
}).then(…);

This works as I expect, but I think I shouldn't need to manually reject, because the value handler does not have to manually resolve.

Yes, you always need to manually return a value if you want to signal a result. Whether that is a plain value, a promise that will fulfill or a promise that is rejected depends on the desired behaviour.

But you don't have to return a rejected promise, you can also just throw an exception:

cookFood().then(eatFood, function() {
    console.error('Error coooking food');
    throw new Error('FOOD_ERROR');
}).then(…);