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



我正在使用Angular JS工作。我试图获得使用$http服务在$scope变量中可访问的json对象。在所有异步AJAX ($http.get())调用中,如果我尝试打印存储在$scope变量中获得的数据并将其打印出来,它会成功工作并显示预期的数据。但是在异步方法的作用域之外,与获得的数据赋值的相同的$scope变量失去了对它的控制,并输出undefined。

代码:

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

时间

console.log($scope.model);
执行

时,$http请求还没有通过,这就是为什么它输出undefined。一旦$http请求完成,您的$scope.model将相应地更新。您可以使用$timeout

来测试这一点
$timeout(function () {
    console.log($scope.model);
}, 5000);

别忘了在控制器中注入$timeout

这让我省心了!$timeout来拯救。感谢dan Moldovan的回答!由于$http服务是异步的,我们必须设置一个计时器来等待一段时间间隔,直到在承诺中真正接收到数据。

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

迄今为止发布的解决方案从根本上是错误的,因为它们依赖于任意超时,并且没有任何东西保证届时异步答案将可用。

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

  1. 你要么只打印回调函数(你已经在你的例子中这样做了)
  2. 或者因为你正在使用angular,你可以设置一个watch (它在后台使用了一个不太好的脏检查解决方案,但至少它是从你的代码中抽象出来的)

如果您想在数据可用时运行一个名为processData的函数,您已经在示例中执行了解决方案1,请参阅这一行:

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

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

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

使用angular的$watch机制:

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

这将在异步回调之后,当数据可用时打印数据,并且程序将从那时开始继续处理。

最新更新