我正在使用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);
}]);
迄今为止发布的解决方案从根本上是错误的,因为它们依赖于任意超时,并且没有任何东西保证届时异步答案将可用。
正如我在上面的评论中建议的那样,这里还有两个数据/事件驱动的解决方案。
- 你要么只打印回调函数(你已经在你的例子中这样做了)
- 或者因为你正在使用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();
}
})
这将在异步回调之后,当数据可用时打印数据,并且程序将从那时开始继续处理。