Ingó Vals
Ingó Vals

Reputation: 4898

Angular problems chaining $resource promises

I was trying to chain some promises for this service I have but the $stateprovider resolves without waiting for $q. This results in my controller getting back the result object with just the empty array, and the object gets filled later on. Where is my promise chain going wrong?

My $stateprovider:

    .state('somestate', {
        resolve: {
            neededvalue: function(anotherservice) {
                return anotherservice.getData(); //this one works pretty well , but doesn't use any chaining
            },
            finalvalue: function(myService, neededvalue) {
                return myService.startChain(neededvalue);
            }
        }
    }

My Service:

    app.factory("myService",
            ['$resource', '$q',
        function ($resource, $q) {

            var firstApi = $resource("api/somewhere/first", {}, { "getData": { method: "POST" } });
            var secondApi = $resource("api/somewhere/second", {}, { "getData": { method: "POST" } });

            var result = {
                array: []
            };

            var myService = {
                startChain: startChain
            };

            return myService;

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

                firstApi
                    .getData(someNeededValues.values).$promise
                    .then(function (data) {
                        result.value = data.value;
                    })
                    .then(recurringAction)
                    .then(deferred.resolve(result));

                return deferred.promise;
            }

            function recurringAction() {
                return secondApi.getData(result.value, function (data) {
                    angular.copy(data.array, result.array);   
                }).$promise;
            }

        }]);

Upvotes: 1

Views: 425

Answers (3)

tomasz stryjewski
tomasz stryjewski

Reputation: 168

not sure if your script worked the way you intended to when you passed deferred.resolve(result) as a callback to promise...

so just change

                .then(deferred.resolve(result));

to

                .then(function(){
                    deferred.resolve(result)
                });

Upvotes: 3

Ingó Vals
Ingó Vals

Reputation: 4898

Well, this was actually a stupid mistake on my behalf.

I needed to wrap the deferred.resolve inside of a function.

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

        firstApi
            .getData(someNeededValues.values).$promise
            .then(function (data) {
                result.value = data.value;
            })
            .then(recurringAction)
            .then(function () {
                deferred.resolve(result);
            });

        return deferred.promise;
    }

Seems like $defer auto resolves or something if there is no .resolve method available.

Upvotes: 1

Pankaj Parkar
Pankaj Parkar

Reputation: 136144

Its an expected behavior of ng-resource promise

From Angular Doc directly

It is important to realize that invoking a $resource object method immediately returns an empty reference (object or array depending on isArray). Once the data is returned from the server the existing reference is populated with the actual data. This is a useful trick since usually the resource is assigned to a model which is then rendered by the view. Having an empty object results in no rendering, once the data arrives from the server then the object is populated with the data and the view automatically re-renders itself showing the new data. This means that in most cases one never has to write a callback function for the action methods.

Upvotes: 1

Related Questions