Angular's $q.reject() vs deferred.reject()
Asked Answered
P

2

64

I'm trying to get a handle on the Angular $q service and its related objects and APIs. When I look at the objects in my console I see:

var deferred = $q.defer()

...(and then from console inspection)...

$q: Object {defer: function, reject: function, when: function, all: function}

deferred: Object {resolve: function, reject: function, notify: function, promise: Object}

deferred.promise: Object {then: function, catch: function, finally: function}

It raises a few questions:

  1. What's the difference between $q.reject() and deferred.reject()? When to use each?
  2. What's the relationship between the errorFn in deferred.promise.then(successFn, errorFn) and the catchFn in deferred.promise.catch(catchFn)?
  3. If I have a bunch of nested promises and an error occurs, will the outermost catch() function always be called? What if one of the nested promises also has a catch function defined? Will that catch prevent the outermost catch from executing?

Thanks.

Pacify answered 27/6, 2014 at 4:2 Comment(0)
P
97

1) $q.reject() is a shortcut to create a deferred and then reject it immediately; I often use this in an errorFn if I can't handle the error.

2) Nothing, promise.catch(errorFn) is just syntactic sugar for promise.then(null, errorFn), just like the success and error methods of the $http service, so you can write code like the following:

promise.
    then(function(result){
        // handle success
        return result;
    }, function errorHandler1(error){
        // handle error, exactly as if this was a separate catch in the chain.

    }).catch(function errorHandler2(error){
        // handle errors from errorHandler1
    });

3) This is exactly where $q.reject can come in handy:

promise.
    catch(function(error){
       //Decide you can't handle the error
       return $q.reject(error); //This forwards the error to the next error handler;
    }).catch(function(error){
       // Here you may handle the error or reject it again.
       return 'An error occurred'; 
       //Now other errorFn in the promise chain won't be called, 
       // but the successFn calls will.
    }).catch(function(error){
       // This will never be called because the previous catch handles all errors.
    }).then(function(result){
       //This will always be called with either the result of promise if it was successful, or 
       //'An error occured' if it wasn't
    });
Prismatoid answered 27/6, 2014 at 4:34 Comment(3)
Thanks for the concise answers. They are very clear. still stuck on number #2 though. Assume your example code provided both a successFn and errorFn in your call to then(). Now under what circumstances will the catchFn run?Pacify
I updated my answer to 2). The catch method is exactly the same as the second argument to the then function. promise.catch(errorFn) is identical to promise.then(null, errorFn).Prismatoid
If anyone wants further reading on when to use $q I found this article very helpful codelord.net/2015/09/24/$q-dot-defer-youre-doing-it-wrongEarmuff
C
5

Ok this is my take from promises.

  1. $q.reject(reason) returns a rejected promise with the reason passed as argument and defered. Reject rejects an existent defered whether its process has finished or not.

  2. errorFn gets launched when a promise is rejected and its argument is the reason why it was rejected. Catch is called when an error inside the promise process wasn't handled properly causeing the promise to raise and exception and not being either rejected or fulfilled .

  3. You shoudn't have nested promises, you should have chained promises in which case the latest catch block should catch everything prior to it if no other block was specified to handle it.

Ceratoid answered 27/6, 2014 at 4:32 Comment(3)
For #2 are you seeing if I'm in my successFn or errorFn and I do a throw new Error(...) then the catchFn will run? My understanding is that is not the case.Pacify
can be in the handlers or in the process. in the process for sure it will catch but i think the hanlder tooCeratoid
the thing is that in the process can occur errors that could prevent the promise from transition to any state, so the catch block is used to detect those errors for instance if your porcess perform a division and you try to divide by 0 you will raise an exception that will automatically exit the process if is not cached and handled. the catch block will get that and act acordingly. maybe i'll juts udate my question because i thimk this is the right behaviorCeratoid

© 2022 - 2024 — McMap. All rights reserved.