Vicheanak Vicheanak - 4 months ago 26
AngularJS Question

How to Check If All $scope are Available in AngularJS?

I have these ngResource queries in my controller:

Ages.query(function(ages){
$scope.ages = ages;
});

Skinissues.query(function(skinissues){
$scope.skinissues = skinissues;
});

Skintypes.query(function(skintypes){
$scope.skintypes = skintypes;
});

Activities.query(function(activities){
$scope.activities = activities;
});


In the same controller in findOne function:

$scope.findOne = function() {

Products.get({
productId: $routeParams.productId
}, function(product) {
for (var i = 0; i < product.ages.length; i ++){
for (var j = 0; j < $scope.ages.length; j ++){
if (product.ages[i].id == $scope.ages[j].id){
$scope.ages[j]['ticked'] = true;
}
}
}
for (var i = 0; i < product.activities.length; i ++){
for (var j = 0; j < $scope.activities.length; j ++){
if (product.activities[i].id == $scope.activities[j].id){
$scope.activities[i]['ticked'] = true;
}
}
}
for (var i = 0; i < product.skintypes.length; i ++){
for (var j = 0; j < $scope.skintypes.length; j ++){
if (product.skintypes[i].id == $scope.skintypes[j].id){
$scope.skintypes[i]['ticked'] = true;
}
}
}
for (var i = 0; i < product.skinissues.length; i ++){
for (var j = 0; j < $scope.skinissues.length; j ++){
if (product.skinissues[i].id == $scope.skinissues[j].id){
$scope.skinissues[i]['ticked'] = true;
}
}
}
for (var i = 0; i < $scope.parents.length; i ++){
if ($scope.parents[i].id == product.parent.id){
$scope.parents[i]['ticked'] = true;
}
}
console.log('Products', product);
$scope.product = product;
});

};


This code, sometimes, it works, sometimes it doesn't, because in the findOne function, sometimes, the
$scope.ages
$scope.skinissues
$scope.skintypes
or
$scope.activities
is undefined.

This happens because their queries haven't finished yet.

What can I do to solve this problem?

Please help. Thanks.

Answer

Use $q.all to resolve the $resource promises.

angular.module('mean.variables')
.factory('Variables', function($q, Products, Ages, Activities, Skinissues, Skintypes, _){

    return {
        get: function(){
            var promiseHash = {};

            promiseHash.ages = Ages.query().$promise;
            promiseHash.skinissues = Skinissues.query().$promise;
            promiseHash.skintypes = Skintypes.query().$promise;
            promiseHash.activities = Activities.query().$promise;
            promiseHash.parents = Products.query().$promise;

            return $q.all(promiseHash);

        }
    }
});

The above example function returns a promise that either resolves sucessfully to a hash of the query objects or resolves rejected with the first rejected response object.

The advantage of using $q.all() instead of $q.defer is that the promise chains aren't broken and error responses are retained for clients of the factory.

From the Docs:

The Resource instances and collections have these additional properties:

  • $promise: the promise of the original server interaction that created this instance or collection.

On success, the promise is resolved with the same resource instance or collection object, updated with data from server. This makes it easy to use in resolve section of $routeProvider.when() to defer view rendering until the resource(s) are loaded.

On failure, the promise is rejected with the http response object, without the resource property.

If an interceptor object was provided, the promise will instead be resolved with the value returned by the interceptor.

--AngularJS ngResource API Reference


all(promises);

Combines multiple promises into a single promise that is resolved when all of the input promises are resolved.

Parameters

An array or hash of promises.

Returns

Returns a single promise that will be resolved with an array/hash of values, each value corresponding to the promise at the same index/key in the promises array/hash. If any of the promises is resolved with a rejection, this resulting promise will be rejected with the same rejection value.

--AngularJS $q Service API Reference -- $q.all

Comments