如何等待多个ngResource $资源查询解析

时间:2016-07-11 16:10:30

标签: angularjs angularjs-scope angular-promise angular-resource

我在控制器中有这些ngResource查询:

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; 
});

在findOne函数的同一个控制器中:

$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;
    });

};

此代码有时会起作用,有时则不起作用,因为在findOne函数中,有时$scope.ages $scope.skinissues $scope.skintypes$scope.activities未定义。

这是因为他们的查询尚未完成。

我该怎么做才能解决这个问题?

请帮忙。感谢。

2 个答案:

答案 0 :(得分:2)

使用$q.all解析$resource承诺。

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);

        }
    }
});

上面的示例函数返回一个promise,它将成功解析为查询对象的哈希值,或者使用第一个被拒绝的响应对象解析 reject

使用$q.all()代替$q.defer的好处是,承诺链不会被破坏,并且会为工厂的客户保留错误响应。

来自文档:

  

资源实例和集合具有以下附加属性:

     
      
  • $promise:创建此实例或集合的原始服务器交互的承诺。
  •   
     

成功时,promise将使用相同的资源实例或集合对象解析,并使用来自服务器的数据进行更新。这使得在resolve section of $routeProvider.when()中使用它很容易推迟视图渲染,直到资源被加载。

     

失败时,使用http response对象拒绝承诺,但不包含resource属性。

     

如果提供了拦截器对象,则将使用拦截器返回的值来解析promise。

- AngularJS ngResource API Reference

  

所有(许诺);

     

将多个promises组合成一个promise,当所有输入promise都被解析时解析。

     

<强>参数

     

承诺的数组或散列。

     

<强>返回

     

返回将使用值的数组/散列解析的单个promise,每个值对应于promises数组/散列中相同索引/键的promise。如果任何承诺通过拒绝得到解决,则此结果承诺将被拒绝并具有相同的拒绝价值。

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

答案 1 :(得分:0)

谢谢你,我通过使用setInterval来检查是否定义了所有变量,从而提出了这项服务。

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

    return {
        get: function(){
            var variables = {};
            var defer = $q.defer();
            Ages.query(function(res){
                variables.ages = res;
            });

            Skinissues.query(function(res){
                variables.skinissues = res;
            });

            Skintypes.query(function(res){
                variables.skintypes = res;
            });

            Activities.query(function(res){
                variables.activities = res; 
            });

            Products.query(function(res){
                variables.parents = res;
            });

            var timer = setInterval(function(){
                if (variables.ages && variables.activities && variables.skinissues && variables.skintypes && variables.parents){
                    defer.resolve(variables);
                    clearInterval(timer);
                }
            }, 50);

            return defer.promise;

        }
    }

}])