13

I know how to chain promises so that multiple success functions are executed. That is esplained in many examples. How do I chain promises so that multiple error functions are executed?

Galdor
  • 1,636
  • 4
  • 23
  • 37

2 Answers2

33

When an error is handled (and, either a value is returned or no value at all), the promise returned from then is considered resolved. You have to return a rejected promise from each error handler in order to propagate and chain error handlers.

For example:

promseA.then(
   function success() {
   },
   function error() {
      return $q.reject();
   })
.promiseB.then(
   function success() {
   },
   function error() {
      return $q.reject();
   })
.promiseC.then(
   function success() {
   },
   function error() {
      return $q.reject();
   });
Michael Kang
  • 52,003
  • 16
  • 103
  • 135
  • 3
    When a rejected promise has an rejection handler that promise still stays rejected since promises never transition once they resolved. The _returned promise_ from the thenable chaining is resolved _if the value returned from the promise error handler is not a rejected promise_ – Benjamin Gruenbaum Apr 13 '15 at 10:11
  • I think we are saying the same thing. When I said "the promise is considered resolved, I was actually referring to the promise returned from the then call. However, my wording could be clearer... – Michael Kang Apr 13 '15 at 10:18
  • Thanks for clarifying, found a duplicate but good answer now nontheless. – Benjamin Gruenbaum Apr 13 '15 at 10:28
  • 1
    @pixelbits, `return $q.reject()` is indeed a better option than `throwing`, but maybe you could add this option to your answer as well so that OP if sees this technique will recognize it. – Max Koretskyi Apr 13 '15 at 11:13
0

then/fail function returns a promise, which can be rejected by throwing errors. If you want to chain multiple error handlers and trigger them all you should throw error from preceding error handlers.

var d = $q.defer();
d.promise.catch(errorHandler1).catch(errorHandler2);
d.reject();

function errorHandler1 {
 throw new Error();
}

function errorHandler2() {
  console.log("I am triggered");
}

Or instead of catch, you can use then method and pass errorHandler1 and errorHandler2 as a second parameter.

Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488
  • 3
    This will log an error to `$exceptionHandler` in Angular, also I don't think this is what OP wants. – Benjamin Gruenbaum Apr 13 '15 at 10:10
  • Right, I didn't know that there is such option `return $q.reject();`. It's much better then throwing an error. Is this also standard for `Q` library and not only angular's `$q`? – Max Koretskyi Apr 13 '15 at 11:11
  • 3
    In Q it's perfectly fine to `throw` since the $exceptionHandler hack does not exist - although you should really not be using Q in new code anymore. – Benjamin Gruenbaum Apr 13 '15 at 11:12
  • _although you should really not be using Q in new code anymore_ - do you mean in angular code? – Max Koretskyi Apr 13 '15 at 11:14
  • No, I mean in general, it's a really old and outdated promise library. Take a look at bluebird for a much much better alternative. (Other alternatives such as When and RSVP are also decent, also - promises are native now anyway) – Benjamin Gruenbaum Apr 13 '15 at 11:15
  • I see, thanks. `Q` is using `Promises/A+` standard as well as native implementations, so I guess the overall approach will be the same, right? Is returning a rejected promise is also `Promises/A+` standard? – Max Koretskyi Apr 13 '15 at 11:20
  • 3
    Yes, returning a rejected promise behaving this way is a requirement of the Promises/A+ standard. It will behave consistently across all Promises/A+ implementations. – Benjamin Gruenbaum Apr 13 '15 at 11:22
  • Thanks, do you know where I can read about when to use throwing or return rejected promise in non-angular applications – Max Koretskyi Apr 13 '15 at 11:29
  • No, but this is literally all there is to it: Throwing and rejecting do the same thing, except `throw`ing will also call `$exceptionHandler` where rejecting will not. This is the code: https://github.com/angular/angular.js/blob/v1.4.0-rc.0/src/ng/q.js#L321-L324 – Benjamin Gruenbaum Apr 13 '15 at 11:30