我希望有人可以帮助我理解我在AngularJS中使用$ scope的烦人问题。请参阅下面代码中的评论:
app.controller('MyController', function ($scope, $routeParams, $http, $timeout) {
$scope.id = $routeParams.id;
$http.get("http://server/api/Blah/GetData/" + $scope.id).success(function (data) {
$scope.data = data;
alert($scope.data.MyObject.Property); //displays the expected value. - Not Undefined or null
}).error(function (data) {
alert(data);
});
$scope.$on('$viewContentLoaded', function () {
$timeout(function () {
var d = document.getElementById("iframe");
d.contentDocument.documentElement.innerHTML = $scope.data.MyObject.Property; //Now MyObject is magically undefined.
}, 0);
});
});
对WEB API的调用返回一个分配给$ scope.data的有效对象。我显示一个警报,以确保$ scope.data.MyObject.Property存在,它确实存在。显示预期值。
现在,当我尝试访问$ viewContentLoaded代码中的$ scope.data.MyObject.Property时,$ scope.data.MyObject不再位于$ scope中。控制台报告以下内容:
HTML1300:导航已发生。 文件:route.html TypeError:无法获取属性' MyObject'未定义或空引用 在匿名函数(http://server/script/route.js:43:13) 在匿名函数(https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js:158:234) 在e(https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js:45:348) 在匿名函数(https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js:48:275)
为什么$ scope会删除$ scope.data.MyObject的值?让这个问题更令人沮丧的是,如果我发出警报("");在$ viewContentLoaded代码中,$ scope.data.MyObject值不再是未定义的。这是怎么回事?
答案 0 :(得分:2)
您需要知道代码执行的时间。
这是带有一些日志记录的固定代码:
app.controller('MyController', function ($scope, $routeParams, $http, $timeout) {
$scope.id = $routeParams.id;
console.log(1);
var promise = $http.get("http://server/api/Blah/GetData/" + $scope.id).success(function (data) {
$scope.data = data;
console.log(2);
alert($scope.data.MyObject.Property); //displays the expected value. - Not Undefined or null
}).error(function (data) {
alert(data);
});
$scope.$on('$viewContentLoaded', function () {
$timeout(function () {
var d = document.getElementById("iframe");
console.log(3);
// d.contentDocument.documentElement.innerHTML = $scope.data.MyObject.Property;
promise.then(function () {
console.log(4);
d.contentDocument.documentElement.innerHTML = $scope.data.MyObject.Property;
});
}, 0);
});
});
您可能希望结果日志为1234
,但实际上可能是1324
。在后一种情况下,$viewContentLoaded
中的代码在 $http.get
成功之前执行。所以它$scope.data
仍为空。
解决方案是在角度世界中使用Promise
(或$q
)。这样您就可以等待$http.get
的结果。您可以保证在 4
之后2
始终执行(假设成功)。
答案 1 :(得分:0)
嗯,这种行为是因为JavaScript代码被执行async
。一旦承诺得到解决,最好包括该代码。
$http.get("http://server/api/Blah/GetData/" + $scope.id).success(function (data) {
$scope.data = data;
alert($scope.data.MyObject.Property); //displays the expected value. - Not Undefined or null
$scope.$on('$viewContentLoaded', function () {
$timeout(function () {
var d = document.getElementById("iframe");
d.contentDocument.documentElement.innerHTML = $scope.data.MyObject.Property; //Now MyObject is magically undefined.
}, 0);
}).error(function (data) {
alert(data);
});
});
这将有效:)
干杯!
答案 2 :(得分:0)
$ http请求是异步的。在触发$ viewContentLoaded事件之前,它可能无法完成。 (我想这个事件在加载DOM之后触发,并且不等待http请求完成,我可能是错的)。 为什么不这样做:
app.controller('MyController', function ($scope, $routeParams, $http, $timeout) {
$scope.id = $routeParams.id;
$http.get("http://server/api/Blah/GetData/" + $scope.id).success(function (data) {
$scope.data = data;
alert($scope.data.MyObject.Property); //displays the expected value. - Not Undefined or null
$timeout(function () {
var d = document.getElementById("iframe");
d.contentDocument.documentElement.innerHTML = $scope.data.MyObject.Property; //Now MyObject is magically undefined.
}, 0);
}).error(function (data) {
alert(data);
});
$scope.$on('$viewContentLoaded', function () {
});
答案 3 :(得分:0)
由于http get是异步功能。你必须使用promises等到http获取结果。 你可以通过以下代码来做到这一点。 提供服务。
app.factory('myService', function($http) {
var getData = function(id) {
// Angular $http() and then() both return promises themselves
return $http({method:"GET", url:"http://server/api/Blah/GetData/" + id}).then(function(result){
// What we return here is the data that will be accessible
// to us after the promise resolves
return result.data; //or may be return result only.
});
};
return { getData: getData };
});
控制器中的
app.controller('MyController', function ($scope, $routeParams, $http, $timeout,myService) {
$scope.id = $routeParams.id;
var Data=myService.getData($scope.id);
Data.then(function(result){
$scope.data.MyObject.Property=result;//or result.data may be
$scope.$on('$viewContentLoaded', function () {
$timeout(function () {
var d = document.getElementById("iframe");
d.contentDocument.documentElement.innerHTML = $scope.data.MyObject.Property; //Now MyObject is magically undefined.
}, 0);
});
});
答案 4 :(得分:-2)
首先,控制器的声明缺少元素。它应该是:
app.controller('MyController', ["$scope" , "$routeParams" , "$http" , function ($scope, $routeParams, $http, $timeout) {...
检查Angular文档中的依赖注入。
尝试此操作,如果仍然无效,请使用新代码和一些记录更新您的问题。