AngularJS $scope 在分配值后删除值
我希望有人能帮助我理解我在 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: Navigation occurred. File: route.html TypeError: Unable to get property 'MyObject' of undefined or null reference at Anonymous function ( http://server/script/route.js:43:13 ) at Anonymous function ( https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js:158:234 ) at e ( https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js:45:348 ) at Anonymous function ( https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js:48:275 )
为什么 $scope 会丢弃 $scope.data.MyObject 的值?如果我在 $viewContentLoaded 代码中放置一个 alert("");,则会使这个问题更加令人沮丧,$scope.data.MyObject 值不再未定义。这里发生了什么事?
您需要了解代码执行的时间。
这是带有一些日志记录的固定代码:
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
(或 Angular 世界中的
$q
)。这样您就可以等待
$http.get
的结果。您必须保证
4
总是在
2
之后执行(假设它成功)。
嗯,这种行为是因为 JavaScript 代码是
异步
执行的。因此最好在承诺得到解决后包含该代码。
$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);
});
});
这会起作用 :)
干杯!
$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 () {
});