开发者问题收集

AngularJS $scope 在分配值后删除值

2016-07-05
268

我希望有人能帮助我理解我在 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 值不再未定义。这里发生了什么事?

3个回答

您需要了解代码执行的时间。

这是带有一些日志记录的固定代码:

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 之后执行(假设它成功)。

Bryan Chen
2016-07-05

嗯,这种行为是因为 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);
    });

});

这会起作用 :)

干杯!

Varit J Patel
2016-07-05

$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 () {

    });
Mahesh
2016-07-05