8

Consider the code:

var myApp = angular.module('myApp', []);

The routes:

myApp.config(['$routeProvider', function($routeProvider) {
        $routeProvider.when('/', {
            templateUrl: 'app.html', 
            controller:myAppController, 
            resolve:{
                resolveData:function(Resolver){
                    return Resolver();
                }
            }
        });
    });

Resolve:

myApp.factory('Resolver', ['$http', function($http){
    return function(){
        return $http({url: '/someurl',method: "GET"}).then(function(data) {

            // dependent call 1
            $http({url: '/someotherurl',method: "GET" }).then(function(data) {

            });

            // dependent call 2
            $http({url: '/someanotherurl',method: "GET" }).then(function(data) {

            });
        });
    }
}]);

Above I have nested 2 calls inside one as they are dependent on the data returned by the parent call.

What I want to do: return the Resolver when all of them have completed and not just the parent call.

I cannot use $q.all() because 2 of the calls are dependent of the first call.

In short, myAppController must be loaded only after all the 3 calls have completed.

pkozlowski.opensource
  • 117,202
  • 60
  • 326
  • 286
AlwaysALearner
  • 43,759
  • 9
  • 96
  • 78

2 Answers2

9

You should be using chaining promise and $q service to solve your problem .Just use the below sample code it should work

 myApp.factory('Resolver', ['$http','$q', function ($http,$q) {
              return function () {
                  var deferred = $q.defer();

                  $http({ url: '/someurl', method: "GET" }).then(function (data) {
                      return $http({ url: '/someurl', method: "GET" })
                  }).then(function (data) {
                      return $http({ url: '/someanotherurl', method: "GET" })
                  }).then(function (data) {
                      deferred.resolve(data);
                  });
                  return deferred.promise;

              }
          }]);
Ajay Beniwal
  • 18,857
  • 9
  • 81
  • 99
  • Hi Ajay! Thanks for the instant reply. But do you think I would be able to pass the data returned by the first call to the subsequent calls if I use chaining? – AlwaysALearner Aug 02 '13 at 07:31
  • yes the data inside every then function is the data returned from previous – Ajay Beniwal Aug 02 '13 at 07:42
  • Chaining did not fit my need very well. I went for nested calls. But $q really helped me fix the thing. Thank you. Voted Up! :) – AlwaysALearner Aug 02 '13 at 10:08
  • If you are using `$resource` instead of `$http`, you need to take extra care to return a promise object. For example, if `SomeService` wraps a resource, you would return it like so: `.then(function(data) { return SomeService.get(...).$promise; })`. The eventual value of that `$promise` object is passed on as the `data` argument to the next function in the chain. – z0r Oct 31 '13 at 02:37
0

This works for me:

            resolve : {
                message: function($q, $route, Restangular) {

                    var msgId = $route.current.params.msgId;
                    var deferred = $q.defer();

                    Restangular.one('message', msgId).get().then(function(message) {
                        Restangular.one('file', message.audioFile.id).get().then(function (blob) {
                            message.blob = blob;
                            deferred.resolve(message);
                        });
                    });
                    return deferred.promise;
                } 
            }