1

I'm trying to use the $q service to resolve multiple promises using the $q.all() function with AngularUI router but for some reasons this fails or it's not working as expected.

This is part of my configuration file that contains the $stateProvider:

.state('home.team',
{
    url : '^/team',
    views : {
        'main' : {
            templateUrl : ConfigProvider.path.views + '/segment/home/team.html',
            controller : 'SegmentHomeTeamCtrl',
            resolve : {
                promiseData : function(ResolveService) { return ResolveService.resolveHomeTeam(); }
            }
        },
        'subMenu' : {
            templateUrl : ConfigProvider.path.views + '/menu/home/team.html'
        }
    }
});

And this is the resolveHomeTeam function located in the Resolve service:

function resolveHomeTeam()
{
    var promises = [];
    promises.push($q.defer());
    UserService.team('me', function(data)
    {
        promises[0].resolve(data);
    }, function()
    {
        promises[0].reject();
    });

    return $q.all(promises);
}

As you can see in this case I'm pushing just one promise into the array and I know for sure that it's being resolved.

Since the only promise is resolved, shouldn't also the promise returned by $q.all() resolved? And shouldn't promiseData data be injected into the SegmentHomeTeamCtrl controller?

If I try to output promiseData inside SegmentHomeTeamCtrl controller I get the whole promise back containing also the actual data returned by the server buy for some reasons I cannot access it.

2
  • What is UserService.team()? Does it return a promise? Commented Jan 28, 2015 at 16:24
  • It just performs an API call to the server and has some callbacks. Commented Jan 28, 2015 at 18:47

2 Answers 2

2

The issue with your code is that you are putting a deferred into your array, not a promise.

And on that note, deferreds are quickly going out of fashion. The preferred way to make a promise (and which is consistent with the ES6 APIs) is to use a promise constructor:

function resolveHomeTeam() {
    var promises = [];

    promises.push($q(function (resolve, reject) {
        UserService.team('me', resolve, reject);
    }));

    return $q.all(promises);
}

Note how this also makes your code quite a bit cleaner.

You could also combine this all into one statement if you wanted to:

function resolveHomeTeam() {
    return $q.all([
        $q(function (resolve, reject) {
            UserService.team('me', resolve, reject);
        })
    ]);
}
Sign up to request clarification or add additional context in comments.

1 Comment

This solved my problem and made things easier for me. Thank you for your time :)
2

You are doing almost everything correctly: you are returning a promise generated by $q.all and you are further returning it in the resolve.

The bug is that you are not creating an array of promises, but rather you pushed a deferred object into the array.

So, change it like so:

var promises = [];
var teamDefer = $q.defer();
promises.push(teamDefer.promise);

UserService.team('me', function(data)
{
   teamDefer.resolve(data);
}, function()
{
   teamDefer.reject();
});

Then you can return $q.all() (as you do):

return $q.all(promises);

Slightly off-topic:

promiseData is incorrectly named, in my opinion, that may indicate a misunderstanding. You should name the variable as the name of the result of you will get. This is what will be injected into your controller, which would not care whether it came from a promise or not. So, probably better to name it team (or something like that)

1 Comment

I found your answer very useful but I decided to chose the other one simply because it was using the promise constructor (that I was unaware of). Thank you anyway for your time and kindness.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.