获取从angularJS中的异步$ http服务获取的对象可在$ scope中全局访问

时间:2015-05-15 09:02:07

标签: javascript angularjs asynchronous

我正在使用Angular JS。我试图获得一个使用$ http服务获得的json对象,可以在$ scope变量中访问。在所有异步AJAX($ http.get())调用中,如果我尝试打印存储在$ scope变量中的数据并打印它,它会成功运行并向我显示预期的数据。但是在异步方法的外部范围内,分配了数据的同一$ scope变量将失去它并打印未定义。

代码:

var app = angular.module('chariot', ['ngRoute', 'ngFileUpload']);
    app.factory('getTestcaseFactory', ['$http', '$routeParams', '$q', function($http, $routeParams, $q) {
       return {
              list: function(){
                var deferred = $q.defer();
                $http.get('/testcase/' + $routeParams.testcase)
                .success(function(data, status, headers, config) {
                    deferred.resolve(data);
                })
                .error(function(data, status, headers, config) {
                    deferred.reject("Error fetching XML file: " + status + ' ' + JSON.stringify(headers));
                });
                return deferred.promise;
              }
            }; 
    }
    ]);
app.controller('testcaseCapCtrl', ['$scope', '$routeParams', '$http', 'getTestcaseFactory', function($scope, $routeParams, $http, getTestcaseFactory) {
    $scope.myjsonobj = '';
    var fetchTestcaseDetails = function() {
    getTestcaseFactory.list()
        .then(
            function(data) {
                $scope.xml.file = data;
                var x2js = new X2JS();
                var jsonObj = x2js.xml_str2json($scope.xml.file);
                $scope.xml.json = JSON.stringify(jsonObj, null, 2);
                $scope.model = jsonObj;
                console.log($scope.model);//PRINTS THE RIGHT DATA
            },
            function(data) {
                alert(data);
            });
    }
fetchTestcaseDetails();
console.log($scope.model); //Prints undefined
}]);

3 个答案:

答案 0 :(得分:0)

到时候

console.log($scope.model);

执行,$http请求尚未通过,这就是它打印未定义的原因。完成$http请求后,您的$scope.model会相应更新。您可以使用$timeout

进行测试
$timeout(function () {
    console.log($scope.model);
}, 5000);

不要忘记在控制器中注入$timeout

答案 1 :(得分:0)

这节省了我的一天! $超时救援。谢谢@Dan摩尔多瓦的答案!由于$ http服务是异步的,我们必须设置一个定时器来等待一个时间间隔,直到在promise.success部分中真正接收数据,然后将它分配给$ scope内的变量。

var app = angular.module('chariot', ['ngRoute', 'ngFileUpload']);
        app.factory('getTestcaseFactory', ['$http', '$routeParams', '$q', function($http, $routeParams, $q) {
           return {
                  list: function(){
                    var deferred = $q.defer();
                    $http.get('/testcase/' + $routeParams.testcase)
                    .success(function(data, status, headers, config) {
                        deferred.resolve(data);
                    })
                    .error(function(data, status, headers, config) {
                        deferred.reject("Error fetching XML file: " + status + ' ' + JSON.stringify(headers));
                    });
                    return deferred.promise;
                  }
                }; 
        }
        ]);
    app.controller('testcaseCapCtrl', ['$scope', '$routeParams', '$timeout', 'getTestcaseFactory', function($scope, $routeParams, $timeout, getTestcaseFactory) {
        var fetchTestcaseDetails = function() {
        getTestcaseFactory.list()
            .then(
                function(data) {
                    $scope.xml.file = data;
                    var x2js = new X2JS();
                    var jsonObj = x2js.xml_str2json($scope.xml.file);
                    $scope.xml.json = JSON.stringify(jsonObj, null, 2);
                    $scope.model = jsonObj;
                    console.log($scope.model);//PRINTS THE RIGHT DATA
                },
                function(data) {
                    alert(data);
                });
        }
    fetchTestcaseDetails();
    $timeout(function() {
      console.log($scope.model); //Prints the Data now
    }, 2000);
    }]);

答案 2 :(得分:0)

到目前为止发布的解决方案是 fundemantally错误,因为它们依赖于任意超时,并且没有任何保证当时可以使用异步答案。

正如我在上面的评论中所建议的,这里还有两个数据/事件驱动的解决方案。

  1. 您要么只在回调函数中打印(您在示例中已经这样做了)
  2. 或者既然你正在使用角度,你可以设置一个手表(在后台使用一个不太好的脏检查解决方案,但至少它从你的代码中抽象出来)
  3. 如果您希望在数据可用后运行名为processData的函数,您已在示例中执行过解决方案1,请参阅以下行:

    console.log($scope.model);//PRINTS THE RIGHT DATA
    

    在这里你可以调用任何其他函数来触发进程的继续,只需调用任何函数:

    console.log($scope.model);//PRINTS THE RIGHT DATA
    processData();
    

    使用angular的$ watch机制(2.):

    $scope.$watch(
        function(){return $scope.model;},
        function(newValue, oldValue){
            if(newValue != null){
                console.log($scope.model);
                processData();
            }
    })
    

    这将在异步回调后打印数据,程序将继续处理。