20

Can somebody tell me if there is a difference between using an error callback vs. a catch function, when using $q.promise please?

E.g. are the two snippets of code functionally equivalent?

function doSomething0() {
    var deferred = $q.defer();

    ...

    return deferred.promise;
 }

 doSomething0()
    .then(doSomething1)
    .then(doSomething2)
    .then(doSomething3)
    .catch(function (err) {
        // do something with `err`
    });

vs.

function doSomething0() {
    var deferred = $q.defer();

    ...

    return deferred.promise;
 }

 function errorHandler(err) {
    // do something with `err`
 }

 doSomething0()
    .then(doSomething1, errorHandler)
    .then(doSomething2, errorHandler)
    .then(doSomething3, errorHandler);

If so, why use the second one? It looks far uglier and leads to more code duplication in my opinion?

keldar
  • 6,152
  • 10
  • 52
  • 82
  • 2
    The second version allows you to bring the promise back into a resolved state to continue with the chain anyway by returning anything other than an error or a rejected promise. – Kevin B Sep 23 '15 at 16:42
  • 2
    And if the error handler throws or returns a rejected promise, it will be called three times. – JB Nizet Sep 23 '15 at 16:44
  • I think `errorHandler` will be called three times only if `doSomething3` fails. But if `doSomething2` fails, it will be called two times and if `doSomething1` fails, it will be called once. – Arashsoft Apr 12 '18 at 14:26

2 Answers2

6

Both will achieve the same thing, except the second one might run errorHandler three times (instead of just once). You are correct that it brings some code duplication, but it also allows you to treat whatever error happened and continue with your chain:

function errorHandler(err) {
  //log error, continue
  return $q.resolve('default value or something');
}

doSomething0()
  .then(doSomething1, errorHandler)
  .then(doSomething2, errorHandler)
  .then(doSomething3, errorHandler);
Marcelo
  • 4,580
  • 7
  • 29
  • 46
  • Thank you! How would I continue with the chain out of interest? Or will it just continue with the chain? – keldar Sep 23 '15 at 17:02
  • 2
    @keldar you just have to return a new `Promise` from your error handler function, just like in the example above! – Marcelo Sep 23 '15 at 17:06
  • 3
    No need to return a promise. You can simply return a value. – JB Nizet Sep 23 '15 at 17:40
  • _"Both will achieve the same thing"_. **Not exactly.** See this please: https://stackoverflow.com/a/65130000/5259296 – AlexMelw Dec 04 '20 at 08:49
2

Let's have a look at the first sample:

doSomething0()
    .then(doSomething1, errorHandler)
    .then(doSomething2, errorHandler)
    .then(doSomething3, errorHandler);


// I've represented functions invocations as if they were synchronous to simplify the example to focus on the error handling
// The above sample is in a way "equivalent" to
try {
    // doSomething0()
    try {
        // doSomething1()
        try {
          // doSomething2()
        } catch(e0) {
           // handle error
        }  
    } catch(e1) {
         // handle error
    }
} catch(e2) {
     // handle error
}
// doSomething3()

But if an exception happens in the doSomething3 handler, it won't be handled.

Ok, let's have a look at the second sample:

doSomething0()
    .then(doSomething1)
    .then(doSomething2)
    .then(doSomething3)
    .catch(function (err) {
        // do something with `err`
    });


// I've represented functions invocations as if they were synchronous to simplify the example to focus on the error handling
// The above sample is in a way "equivalent" to
try {
    // doSomething0()
    // doSomething1()
    // doSomething2()
    // doSomething3()
}
catch(e) {
    // Catch 'em all
    console.log(e)
}
AlexMelw
  • 2,406
  • 26
  • 35