异步代码中需要同步

时间:2014-06-15 19:59:37

标签: javascript angularjs

我正在尝试为角度模块创建一个工厂,该工厂返回通过角度$http.get()收到的JSON对象。

success()的回调函数中,我试图将对象分配给变量products。在分配发生之前,似乎products正在从工厂函数返回。

有人可以建议如何同步下面的代码吗?在return products;完成之前,我们如何延迟$http.get('/products').success();的执行? 还有更好的方法吗?

angular.module('app', ['ngRoute'])
    .factory('products', ['$http',function ($http) {
        var products;
        $http.get('/products').success(function(data,status,header,config){
            products=data;
            console.log(products); //[Object, Object, Object]
        });
        console.log(products); //undefined
        return products;
    }])

更新

angular.module('app', [])
        .factory('members1', ['$http',
            function ($http) {
                var members1=[];
                $http({
                    method: 'GET',
                    url: '/members.json'
                }).success(function (data, status, headers, cfg) {
                    members1=data;
                });
                return members1;
            }])
        .factory('members2', ['$http',
            function ($http) {
                var members2=[];
                $http({
                    method: 'GET',
                    url: '/members.json'
                }).success(function (data, status, headers, cfg) {
                    angular.copy(data,members2);
                });
                return members2;
            }])
        .controller('controller1', ['$scope','members1','members2',
            function ($scope,members1,members2) {
                $scope.members1=members1;
                $scope.members2=members2;
            }]);

上面的代码有两个相同的工厂,只有一个区别(angular.copy而不是赋值)。具有angular.copy的那个适用于以下模板。

<div ng-controller="controller1">
    <div>
        Using Members1 Factory
        <ul>
            <li ng-repeat="member in members1">{{member.name}}</li>
        </ul>
    </div>
    <div>
        Using Members2 Factory
        <ul>
            <li ng-repeat="member in members2">{{member.name}}</li>
        </ul>
    </div>
</div>

观点:

Using Members1 Factory
Using Members2 Factory
Name1
Name2
Name3

4 个答案:

答案 0 :(得分:1)

在我看来,解决这个问题的最佳方法是使用$ http默认返回的承诺。

angular.module('app', ['ngRoute'])
    .factory('products', ['$http',function ($http) {
        return $http.get('/products');
    }]);

然后在您的控制器/指令/您想要注射工厂的任何地方,你可以使用类似的东西:

angular.module('app').controller('ExampleCtrl', function ($scope, products) {

    products.then(function (data) {
        $scope.products = data;
    });

});

答案 1 :(得分:1)

我相信,您希望将数据逻辑封装在服务中。这是一种更清洁的方法。

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

app.factory('products', ['$http',function ($http,$q) {

        return{
           getAll:function(){
               var deffered = $q.defer();
               $http.get('/products').success(function(data,status,header,config){
                    deffered.resolve(data);

               }).error(function(status){
                    deffered.reject(status);
               });

               return deffered.promise;
           }
        };


    }]);

app.controller('myController',function myController($scope, products){
     products.getAll().then(function(data){
          //the property that needs to bind on view
          $scope.products=data;
     });
});

答案 2 :(得分:1)

我更喜欢从服务返回数据的方法(最初会为空)并在解析$ http promise后填充它,同时保留数组引用:

angular.module('app', ['ngRoute'])
    .factory('products', ['$http',function ($http) {
        var products = [];
        $http.get('/products').success(function(data,status,header,config){
            angular.copy(data, products);
            console.log(products); //[Object, Object, Object]
        });
        console.log(products); // empty initially, populated when promise resolved.
        return products;
    }])

答案 3 :(得分:0)

好消息是你很亲密。 $http.get方法旨在满足您的需求,因此其返回值为promise(如果这对您没有多大帮助,那么您需要了解角度{{3} })

因此,您不要尝试自己返回产品,而只是返回承诺并使用它