0
votes

I am using AngularJS, I have a function in a service with nested promises:

this.getOfferStatus = function (offer) {

    if(offer.isDraft){
        return 'Draft';
    } else {
        this.isProcessed(offer).then(function (isProcessed) {
            if (isProcessed) {
                this.isAccepted(offer).then(function (isAccepted) {
                    if (isAccepted) {
                        if (isExpired(offer)) {
                            return 'Expired';
                        } else {
                            if (this.isActive(offer).then(function (isActive) {
                                    return 'Active';
                                }, function (err) {
                                    console.error(err);
                                }));
                            }
                        } else {
                            return 'Rejected';
                        }
                    }, function (err) {
                        console.error(err);
                    })
                } else {
                    return 'Pending';
                }
            }, function (err) {
                console.error(err);
            });
        }
    }
}

But, when I call this function in my controller, I get this error:

XHR finished loading: GET "http://localhost:8080/localbusiness/1/offers/Absolute". Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting! Watchers fired in the last 5 iterations: [] http://errors.angularjs.org/1.5.0/$rootScope/infdig?p0=10&p1=%5B%5D at angular.js:68 at Scope.$digest (angular.js:16702) at Scope.$apply (angular.js:16928) at done (angular.js:11266) at completeRequest (angular.js:11464) at XMLHttpRequest.requestLoaded (angular.js:11405) Uncaught Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting! Watchers fired in the last 5 iterations: []


isProcessed() function:

this.isProcessed = function (offer) { 
    var deferred = $q.defer();
    var LocalBusinessResource =
        $resource(apiService + '/offers/:id/processed', {id: '@id'});
    LocalBusinessResource.get({id: offer.id}, function (result) {
        deferred.resolve(result); 
    }, function (err) { 
        return $q.reject(err);
        alert('check your server connection ' + angular.toJson(err)); 
    });
    return deferred.promise; 
}

In my controller:

$scope.getStatus = function(offer){ 
    return offerService.getOfferStatus(offer);
}; 
2
Don't return anything before function end. return after all your function executed. - Arun Shinde
You're also trying to return bare strings instead of resolved promises; that isn't going to work either. - Daniel Beck
@ArunShinde do you have any fixes? - jemlifathi
What does isProcessed() do? I suspect that is creating an infinite recursive loop. Also using the this keyword inside a fulfillment handler of a .then method won't work. The promise spec says that the this keyword should be undefined in strict mode and the global context in sloppy mode. - georgeawg
@georgeawg here is isProcessed() function: this.isProcessed = function (offer) { var deferred = $q.defer(); var LocalBusinessResource = $resource(apiService + '/offers/:id/processed', {id: '@id'}); LocalBusinessResource.get({id: offer.id}, function (result) { deferred.resolve(result); }, function (err) { return $q.reject(err); alert('check your server connection ' + angular.toJson(err)); }); return deferred.promise; } - jemlifathi

2 Answers

0
votes

Check this might solve your problem.

this.getOfferStatus = function (offer) {
   var parent = this;
    if(offer.isDraft){
        parent.setStatus('Draft')
    }else{
        this.isProcessed(offer).then(function (isProcessed) {
            if (isProcessed) {
                this.isAccepted(offer).then(function (isAccepted) {
                    if (isAccepted) {
                        if (isExpired(offer)) {
                            parent.setStatus('Expired')
                        } else {
                            if (this.isActive(offer).then(function (isActive) {
                                    parent.setStatus('Active')
                                }, function (err) {
                                    console.error(err);
                                }));
                        }
                    }else{
                        parent.setStatus('Rejected')
                    }
                }, function (err) {
                    console.error(err);
                }) 
            } else {
                parent.setStatus('Pending')
            }
        }, function (err) {
            console.error(err);
        });
    }

}

this.setStatus = function(status){
    $scope.status = status;
}
0
votes

@georgeawg I expect getOfferStatus to return a string

The function only returns a string when offer.isDraft is truthy otherwise it returns null.

this.getOfferStatus = function (offer) {

    if(offer.isDraft){
        //Returns a string here
        return 'Draft';
    }else{
        this.isProcessed(offer).then(function anon1(isProcessed) {
            if (isProcessed) {
                this.isAccepted(offer).then(function anon2(isAccepted) {
                    if (isAccepted) {
                        if (isExpired(offer)) {
                            //This returns to function anon2
                            return 'Expired';
                        } else {
                            if (this.isActive(offer).then(function anon3(isActive) {
                                    //This returns to anon3
                                    return 'Active';
                                }));
                        }
                    }else{
                        //This returns to anon2
                        return 'Rejected';
                    }
                })
            } else {
                //This returns to anon1
                return 'Pending';
            }
        }, function (err) {
            console.error(err);
        });
    }
//
//Returns null here
//
}

There is only one return statement that returns to getOfferStatus. All the other return statements are inside anonymous functions inside .then methods.

It is erroneous to think those return statements will return a string to a parent (or grandparent) function. Returns need to be done for every level of nesting.