AngularJS deferred.reject not working but $q.reject working
Asked Answered
S

3

5

I am confused between Angular JS deferred and $q. I found this SO Question that explains the difference between $q.defer() and $q.It explains

$q.reject is a shortcut to create a deferred and then reject it immediately

So $q.reject() must be equal to

var deferred = $q.defer(); deferred.reject(), if not please explain the actual difference between the two.

But in my case, $q.reject() is working, but deffered.reject() is not working. Also we need to return rejected promised like $q.reject() but not deferred.reject(). I have seen examples where there is no return on deffered.reject()

This is the code

 var deferred = $q.defer();
 myService.getData()
 .then(function(response){
   deferred.notify('Just a notification');
   deferred.reject('rejected');
 })
 .then(function(response) {
   console.log('done');      
 }, function(response) {
   console.log('rejected');
 })

This is not working, but when I replaced deferred.reject with $q.reject(), the promise has been rejected and the control is moved to the error function of the followed then block.

Any help is greatly appreciated. Thanks in advance.

Spitsbergen answered 11/7, 2015 at 17:39 Comment(1)
it won't work in your scenario at all, you chained .then(function (response... onto the promise that .getData() has returned, not the promise that deferred has return. Why should this work? it doesn't make sense.Prod
H
5

It doesn't work when you use deferred.reject because you are not returning new rejected promise. You can use both $q.reject() and deferred.reject() you just need to return a promise in both cases.

You need to to understand that

  • $q.reject() is rejected promise object
  • deferred.reject() is not a promise, but deferred object which has rejected promise in one of its properties (namely, $promise).

So you can return any object or value and it will become a new promise object and will be passed to the next then block in chain. However, when you return deferred.reject() it will be passed as just some object (one more time, it is not a promise, but it has a promise inside) and next promise will get resolved successfully of course.

It will work properly with deferred too if you return corresponding promise:

var deferred = $q.defer();
myService.getData()
    .then(function(response) {
        deferred.notify('Just a notification');
        deferred.reject('rejected');
        return deferred.promise;
        //return $q.reject();
    })
    .then(function(response) {
        console.log('done');
    }, function(response) {
        console.log('rejected');
    });

And finally answer to you question: $q.reject() is a promise object with status "rejected". deferred.reject() is not a promise, but it has rejected promise object inside as deferred.$promise. What to use? You should use $q.reject(), using dummy deferred object is redundant in this case and considered bad practice, in fact it even has a name as deferred anti-pattern.

Haircut answered 11/7, 2015 at 17:56 Comment(4)
Great Answer! Thanks a lot. Just another question. What is actually a promise object and diferred object.Spitsbergen
The promise object is available at deferred.promise. Got it when I logged the object.Spitsbergen
My doubt is the diferred.promise we are returning is different from the response object we are getting in error block. What is heppening behind the scenes?Spitsbergen
deferred.$promise isnt a thingProd
G
2

Make sure you are returning a promise.

function getData() {
    var deferred = $q.defer();
    myService.getData()
        .then(function (response) {
           deferred.resolve('Just received a notification');
        }).catch(function (err) {
           deferred.reject(err); 
        };

    return deferred.promise;
}

getData().then(function (response) {
    console.log('done');
}, function (response) {
    console.log('rejected');
});
Greatly answered 11/7, 2015 at 17:51 Comment(2)
I actually have this code snippet inside my controller. Could you please explain why I should return a promise.Spitsbergen
Sure, a promise is what has the properties of .then, .catch, .finally so you must return the promise so it can be fulfilled. When you are doing $q.reject you are returning a fulfilled promise, albeit rejected.Greatly
L
0

This is working with Q (https://github.com/kriskowal/q)

var def = Q.defer();
def.promise
.then(
    function(ok){
        return ok;
    },
    function(err){
        var d = Q.defer();
        d.reject(err);
        return d.promise;
    }
)
.then(
    function(ok){
        console.log('ok',ok);
    },
    function(err){
        console.log('err',err);
    }
);
def.reject('error');
Lorin answered 27/11, 2015 at 11:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.